wspromisify 2.9.4 → 2.10.0

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/README.md CHANGED
@@ -11,7 +11,7 @@ const responseData = await ws.send({catSaid: 'Meow!'})
11
11
  ```
12
12
 
13
13
  // If you detected some bug, want some stuff to be added, feel free to open an issue!
14
- Large data support (chunking), plugins, streams and different server-side implementations are coming.
14
+ Large data support (chunking), plugins and different server-side implementations are coming.
15
15
  To see a Node.js server-side part example, please, take a look on test/mock in github repo.
16
16
 
17
17
 
@@ -21,6 +21,7 @@ Features (almost all are tunable via constructor config below.)
21
21
  - ES-module and commonjs built-in.
22
22
  - Types (d.ts) included.
23
23
  - Automatically reconnects.
24
+ - Streams are supported. For example, you can stream your AI response.
24
25
  - Supports existent native WebSocket or ws-like implementation (ws npm package) via `socket` property.
25
26
  - And provide your own socket instance via socket config prop.
26
27
  - Any id and data keys to negotiate with your back-end.
@@ -71,7 +72,7 @@ Default constructor config is
71
72
  socket: null,
72
73
  // You can set your own middleware here.
73
74
  adapter: ((host, protocols) => new WebSocket(host, protocols)),
74
- // You can replace original serialisation to your own or even binary stuff.
75
+ // You can replace original serialisation to your own or even binary stuff. Eg MessagePack or CBOR.
75
76
  encode: (message_id, message_data, config) => data,
76
77
  // You can replace original deserialisation to your own or even
77
78
  // making the message object from binary data.
@@ -106,14 +107,16 @@ Methods:
106
107
  ready()
107
108
  // sends any type of message and returns a Promise.
108
109
  send(message),
110
+ // Streams as async generator, resolving in chunks.
111
+ // The server must send the same id for chunks then add done: true in the last one.
112
+ *stream(message),
109
113
  // .addEventListener with optional predicate that works after reconnections.
110
114
  on(event_name, handler, predicate = (WebSocketEvent) => true),
111
115
  // Closes the connection and free up memory. Returns Promise that it has been done.
112
116
  close()
113
-
114
117
  ```
115
118
 
116
- Example:
119
+ Example (more in `tests` dir in the repo):
117
120
  ```javascript
118
121
 
119
122
  import WSP from 'wspromisify' // or const WSP = require('wspromisify') in Node.
package/dist/bundle.cjs CHANGED
@@ -1 +1 @@
1
- "use strict";const e=Symbol("Placeholder"),t=t=>{let n=0;for(const s of t)s!==e&&n++;return n},n=(t,n)=>{const s=t.length,o=t.slice(),i=n.length;let r=i,l=0;for(;r&&l<s;l++)o[l]===e&&(o[l]=n[i-r],r--);for(l=s;r;l++,r--)o[l]=n[i-r];return o},s=(e,o,i)=>{const r=e.length-o.length-t(i);if(r<1)return e(...n(o,i));{const t=(...t)=>s(e,n(o,i),t);return t.$args_left=r,t}},o=e=>(...n)=>e.length>t(n)?s(e,[],n):e(...n);function i(t){return function(n,s){const o=n===e,i=arguments.length;if(1===i&&o)throw new Error("Senseless placeholder usage.");return i>1?o?(t=>function(n){return n===e?t:t(n)})((e=>t(e,s))):t(n,s):e=>t(n,e)}}function r(e){return o(e)}const l=void 0,c=1/0,a=e=>typeof e,u=e=>null===e,h={u:"U",b:"B",n:"N",s:"S",f:"F"},f=Symbol(),d=e=>{const t=a(e);return"object"===t?u(e)?"Null":e.constructor.name:h[t[0]]+t.slice(1)},g=e=>e.length,p=i(((e,t)=>e===t)),m=i(((e,t)=>{const n=d(e);if(p(n,d(t))&&(p(n,"Object")||p(n,"Array"))){if(u(e)||u(t))return p(e,t);if(p(e,t))return!0;for(const n of[e,t])for(const s in n)if(!(p(n,t)&&s in e||p(n,e)&&s in t&&m(e[s],t[s])))return!1;return!0}return p(e,t)})),y=i(((e,t)=>(t.push(e),t))),w=r(((e,t,n)=>n.reduce(e,t))),_=o(((e,t,n,s)=>e(s)?t(s):n(s))),b=(...t)=>(...n)=>{let s,o=!0;for(let i=g(t)-1;i>-1;i--)o?(o=!1,s=t[i](...n)):s=s===e?t[i]():t[i](s);return s},S=i(((e,t)=>t[e])),k=r(((e,t,n)=>n.slice(e,(e=>"number"==a(e))(t)?t:c))),P=S(0);k(1,c);const v=i(((e,t)=>t.find(e))),E=e=>()=>e,N=i(((e,t)=>t.split(e))),q=E(!0),A=E(!1),W=i(((e,t)=>w(((t,n)=>v((t=>e(n,t)),t)?t:y(n,t)),[],t)))(m),$=r(((e,t,n)=>g(t)?(e=>u(e)||(e=>e===l)(e))(n)?e:b((s=>s in n?$(e,k(1,c,t),n[s]):e),P)(t):n));$(l),b(_(m(f),A,q),$(f));const j=i(((e,t)=>t.map(e))),{floor:z}=Math,C="0123456789abcdefghijklmnopqrstuvwxyz",Q=b((e=>Object.fromEntries(e)),j(((e,t)=>[e,t])),N(""));class O{abc;abclen;c2pos;standard;setABC(e){if(!b(m(g(t=e)),g,W,N(""))(t))throw new Error("Not all chars are unique!");var t;this.abc=e,this.abclen=e.length,this.standard=C.startsWith(e),this.c2pos=Q(e)}zip(e){const{abc:t,abclen:n}=this;let s="";for(;e>0;)s=t[e%n]+s,e=z(e/n);return s||"0"}unzip(e){const{standard:t,abclen:n,c2pos:s}=this;if(t)return parseInt(e,n);const o=e.length;let i=0;for(let t=0;t<o;t++)i+=s[e[t]]*n**(o-t-1);return i}constructor(e){this.setABC(e||C+"ABCDEFGHIJKLMNOPQRSTUVWXYZ")}}const R=new O;R.setABC.bind(R),R.zip.bind(R),R.unzip.bind(R);const T=(()=>{try{return WebSocket||null}catch{return null}})(),x=(e,t,n)=>e.addEventListener(t,n),B=(e,t)=>setTimeout(t,e),I={data_type:"json",log:()=>null,timer:!1,url:"localhost",timeout:1400,reconnect:2,reconnection_attempts:1/0,max_idle_time:1/0,lazy:!1,socket:null,adapter:(e,t)=>new WebSocket(e,t),encode:(e,t,{server:n})=>JSON.stringify({[n.id_key]:e,[n.data_key]:t}),decode:e=>JSON.parse(e),protocols:[],pipes:[],server:{id_key:"id",data_key:"data"},ping:{interval:55,content:{}}},M=Symbol("Placeholder"),D=e=>{let t=0;for(const n of e)n!==M&&t++;return t},L=(e,t)=>{const n=e.length,s=e.slice(),o=t.length;let i=o,r=0;for(;i&&r<n;r++)s[r]===M&&(s[r]=t[o-i],i--);for(r=n;i;r++,i--)s[r]=t[o-i];return s},U=(e,t,n)=>{const s=e.length-t.length-D(n);if(s<1)return e(...L(t,n));{const o=(...s)=>U(e,L(t,n),s);return o.$args_left=s,o}},F=e=>(...t)=>e.length>D(t)?U(e,[],t):e(...t);function J(e){return function(t,n){const s=t===M,o=arguments.length;if(1===o&&s)throw new Error("Senseless placeholder usage.");return o>1?s?(e=>function(t){return t===M?e:e(t)})((t=>e(t,n))):e(t,n):n=>e(t,n)}}function G(e){return F(e)}const H=/^(.*?)(8|16|32|64)(Clamped)?Array$/,K=void 0,V=1/0,X=e=>typeof e,Y=e=>null===e,Z=e=>"number"==X(e);const ee=e=>Y(e)||(e=>e===K)(e),te={u:"U",b:"B",n:"N",s:"S",f:"F"},ne=Symbol(),se=e=>{const t=X(e);return"object"===t?Y(e)?"Null":e.constructor.name:te[t[0]]+t.slice(1)},oe=J(((e,t)=>se(t)===e)),ie=e=>e.length,re=J(((e,t)=>e===t)),le=J(((e,t)=>{const n=se(e);if(re(n,se(t))&&(re(n,"Object")||re(n,"Array")||(e=>H.test(e))(n))){if(Y(e)||Y(t))return re(e,t);if(re(e,t))return!0;for(const n of[e,t])for(const s in n)if(!(re(n,t)&&s in e||re(n,e)&&s in t&&le(e[s],t[s])))return!1;return!0}return re(e,t)})),ce=J(((e,t)=>(t.push(e),t))),ae=G(((e,t,n)=>n.reduce(e,t))),ue=J(((e,t)=>{const n=(e=>Array.isArray(e))(t);let s,o;n&&(s=0,o=[]);for(let s in t)e(t[s],s)||(n?o.push(+s):delete t[s]);if(n)for(const e of o)t.splice(e-s++,1);return t})),he=F(((e,t,n,s)=>e(s)?t(s):n(s))),fe=(...e)=>(...t)=>{let n,s=!0;for(let o=ie(e)-1;o>-1;o--)s?(s=!1,n=e[o](...t)):n=n===M?e[o]():e[o](n);return n},de=J(((e,t)=>t[e])),ge=G(((e,t,n)=>n.slice(e,Z(t)?t:V))),pe=de(0);ge(1,V);const me=J(((e,t)=>t.find(e))),ye=e=>()=>e,we=J(((e,t)=>(e(t),t))),_e=ye(!0),be=ye(!1),Se=J(((e,t)=>t(...e))),ke=e=>(...t)=>{const n=e(...t),s=function(e){return"function"===X(e)}(n);return!s||s&&n.$args_left<=0?(e=>!e)(n):ke(n)},Pe=J(((e,t)=>ae(((t,n)=>me((t=>e(n,t)),t)?t:ce(n,t)),[],t)));Pe(le);const ve=e=>{let t,n=!1;return function(...s){return n?t:(n=!0,t=e(...s))}},Ee=G(((e,t,n)=>ie(t)?ee(n)?e:fe((s=>s in n?Ee(e,ge(1,V,t),n[s]):e),pe)(t):n));Ee(K),fe(he(le(ne),be,_e),Ee(ne));const Ne=G(((e,t,n)=>t(n)&&e(n))),qe=ke,{random:Ae}=Math,We=new O,$e=Se([]),je=Ne(oe("Number"),qe(isNaN)),ze={_is_ping:!0},Ce=e=>e&&clearTimeout(e),Qe=e=>{const t=We.zip(2147483637*Ae()|0);return t in e?Qe(e):t};module.exports=class{ws=null;intentionally_closed=!1;reconnect_timeout=null;queue={};onReadyQueue=[];onCloseQueue=[];handlers={open:[],close:[],message:[],error:[],timeout:[]};config={};ping_timer=null;idle_timer=null;get opened(){return 1===this.ws?.readyState}init_flush(){ue(be,this.queue)}call(e,...t){for(const n of this.handlers[e])n(...t)}log(e,t=null,n=null){const{config:s}=this;null===n?s.timer?s.log(e,null,t):s.log(e,t):s.log(e,n,t)}resetPing(){const{config:{ping:e},ping_timer:t}=this;e&&(ee(t)||clearTimeout(t),this.ping_timer=B(1e3*e.interval,(async()=>{const{ping_timer:t,opened:n}=this;n?(await this.send(e.content,ze),this.resetPing()):clearTimeout(t)})))}resetIdle(){const{config:{max_idle_time:e},idle_timer:t}=this;e!==1/0&&(ee(t)||clearTimeout(t),this.idle_timer=B(1e3*e,(()=>this.opened&&this.close())))}initSocket(e){const{queue:t,config:n}=this;this.ws=e,this.onReadyQueue.forEach((e=>e())),this.onReadyQueue.splice(0);const{id_key:s,data_key:o}=n.server;this.call("open",e);for(const n in t)e.send(t[n].msg);null!==this.reconnect_timeout&&(clearInterval(this.reconnect_timeout),this.reconnect_timeout=null),this.resetPing(),this.resetIdle(),x(e,"close",(async(...e)=>{this.log("close"),this.ws=null,this.onCloseQueue.forEach($e),this.onCloseQueue.splice(0),this.call("close",...e);let{reconnect:t,reconnection_attempts:s}=n;if(je(t)){const e=async()=>{if(this.intentionally_closed||!s)return;s--,this.log("reconnect"),ee(this.ws)||(this.ws.close(),this.ws=null);const n=await this.connect();ee(n)||(this.reconnect_timeout=setTimeout(e,1e3*t))};e()}})),x(e,"message",(e=>{try{const t=n.decode(e.data);if(this.call("message",{...e,data:t}),s in t){const e=this.queue[t[s]];if(e){const n=e.sent_time?Date.now()-e.sent_time:null;this.log("message",t[o],n),e.ff(t[o])}}}catch(t){console.error(t,`WSP: Decode error. Got: ${e.data}`)}this.resetPing()}))}opening=!1;connect(){return new Promise((e=>{if(this.opened||this.opening)return e(null);this.opening=!0;const t=this.config,n=t.socket||t.adapter(t.url,t.protocols);if(!n||n.readyState>1)return this.opening=!1,this.ws=null,this.log("error","ready() on closing or closed state! status 2."),e(2);const s=ve((t=>{this.opening=!1,e(t)}));x(n,"error",ve((e=>{this.ws=null,this.log("error","status 3. Err: "+e.message),this.call("error",e),s(3)}))),n.readyState?(this.initSocket(n),s(null)):x(n,"open",ve((()=>{this.log("open"),this.initSocket(n),s(null)})))}))}get socket(){return this.ws}async ready(){return new Promise((e=>{this.config.lazy||this.opened?e():this.onReadyQueue.push(e)}))}on(e,t,n=_e,s=!1){const o=e=>n(e)&&t(e);return s?x(this.ws,e,o):this.handlers[e].push(o),o}off(e,t,n=!1){if(n)return((e,t,n)=>e.removeEventListener(t,n))(this.ws,e,t);const s=this.handlers[e],o=s.indexOf(t);~o&&s.splice(o,1)}async close(){return new Promise(((e,t)=>{null===this.ws?t("WSP: closing a non-inited socket!"):(this.onCloseQueue.push((()=>{this.init_flush(),e(null)})),this.ws.close(),this.ws=null,this.intentionally_closed=!0)}))}open(){if(!this.opened)return this.intentionally_closed=!1,this.connect()}async prepareMessage(e,t={}){this.log(t._is_ping?"ping":"send",e);const{config:n,queue:s}=this,{pipes:o,server:{data_key:i}}=n,{top:r,_is_ping:l}=t,c=Qe(s);if("object"==typeof r&&r[i])throw new Error(`Attempting to set data key/token via ${t._is_ping?"ping":"send"}() options!`);for(const t of o)e=t(e);const[a,u]=await Promise.all([n.encode(c,e,n),this.connect()]);if(u)throw new Error("ERR while opening connection #"+u);this.opened&&(this.ws.send(a),this.resetPing(),l||this.resetIdle());const h=we((()=>delete this.queue[c]));return{message_id:c,msg:a,timeout:t=>B(n.timeout,(()=>{c in s&&(this.call("timeout",e),t({"Websocket timeout expired":n.timeout,"for the message":e}),h())})),cleanup:h}}async send(e,t={}){const{message_id:n,msg:s,timeout:o,cleanup:i}=await this.prepareMessage(e,t),{queue:r,config:l}=this;return new Promise(((e,t)=>{const i=o(t);r[n]={msg:s,data_type:l.data_type,sent_time:l.timer?Date.now():null,ff(t){Ce(i),e(t)}}})).finally(i)}async*stream(e,t={}){const{message_id:n,msg:s,timeout:o,cleanup:i}=await this.prepareMessage(e,t),{queue:r,config:l}=this;let c,a=!1,u=null;for(r[n]={msg:s,ff:e=>{c(e),e?.done&&(i(),a=!0)},data_type:l.data_type,sent_time:l.timer?Date.now():null};!a;)yield await new Promise(((e,t)=>{u=o(t),c=e})).catch((e=>i(e))).finally((()=>{Ce(u),u=null}))}constructor(e={}){this.config=(e=>{if(null===T&&!("adapter"in e))throw new Error("\n This platform has no native WebSocket implementation.\n Please use 'ws' package as an adapter.\n See https://github.com/houd1ni/WebsocketPromisify/issues/23\n ");const t=Object.assign({},I,e),n=t.url;if("/"==n[0])try{const e=location.protocol.includes("s:")?"wss":"ws";t.url=`${e}://${location.hostname}:${location.port}${n}`}catch(e){throw new Error("WSP: URL starting with / in non-browser environment!")}return t})(e),this.config.lazy||this.connect()}};
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:!0});const t=Symbol("Placeholder"),e=e=>{let n=0;for(const s of e)s!==t&&n++;return n},n=(e,n)=>{const s=e.length,i=e.slice(),o=n.length;let r=o,l=0;for(;r&&l<s;l++)i[l]===t&&(i[l]=n[o-r],r--);for(l=s;r;l++,r--)i[l]=n[o-r];return i},s=(t,i,o)=>{const r=t.length-i.length-e(o);if(r<1)return t(...n(i,o));{const e=(...e)=>s(t,n(i,o),e);return e.$args_left=r,e}},i=t=>(...n)=>t.length>e(n)?s(t,[],n):t(...n);function o(e){return function(n,...s){return s.length>0?n===t?(e=>function(n){return n===t?e:e(n)})((t=>e(t,s[0]))):e(n,s[0]):t=>e(n,t)}}function r(t){return i(t)}const l=t=>t.length,c=/^(.*?)(8|16|32|64)(Clamped)?Array$/,u=void 0,a=1/0,h=t=>typeof t,d=t=>null===t,f=t=>"number"==h(t);const p=t=>d(t)||(t=>t===u)(t),g={u:"U",b:"B",n:"N",s:"S",f:"F"},m=Symbol(),y=t=>{const e=h(t);return"object"===e?d(t)?"Null":t.constructor.name:g[e[0]]+e.slice(1)},_=o(((t,e)=>y(e)===t)),w=o(((t,e)=>t===e)),b=o(((t,e)=>{const n=y(t);if(w(n,y(e))&&(w(n,"Object")||w(n,"Array")||(t=>c.test(t))(n))){if(d(t)||d(e))return w(t,e);if(w(t,e))return!0;for(const n of[t,e])for(const s in n)if(!(w(n,e)&&s in t||w(n,t)&&s in e&&b(t[s],e[s])))return!1;return!0}return w(t,e)})),k=o(((t,e)=>(e.push(t),e))),S=r(((t,e,n)=>n.reduce(t,e))),P=o(((t,e)=>{const n=(t=>Array.isArray(t))(e);let s,i;n&&(s=0,i=[]);for(let s in e)t(e[s],s)||(n?i.push(+s):delete e[s]);if(n)for(const t of i)e.splice(t-s++,1);return e})),v=i(((t,e,n,s)=>t(s)?e(s):n(s))),E=(...e)=>(...n)=>{let s,i=!0;for(let o=l(e)-1;o>-1;o--)i?(i=!1,s=e[o](...n)):s=s===t?e[o]():e[o](s);return s},A=o(((t,e)=>e[t])),C=r(((t,e,n)=>n.slice(t,f(e)?e:a))),j=A(0);C(1,a);const N=o(((t,e)=>e.find(t))),W=t=>()=>t,$=o(((t,e)=>(t(e),e))),q=W(!0),O=W(!1),x=o(((t,e)=>e(...t))),z=t=>(...e)=>{const n=t(...e),s=function(t){return"function"===h(t)}(n);return s&&n.$args_left?z(n):(t=>!t)(n)},Q=o(((t,e)=>S(((e,n)=>N((e=>t(n,e)),e)?e:k(n,e)),[],e)));Q(b);const T=t=>{let e,n=!1;return function(...s){return n?e:(n=!0,e=t(...s))}},R=(t,e,n)=>l(e)?p(n)?t:E((s=>s in n?R(t,C(1,a,e),n[s]):t),j)(e):n,B=r(R);B(u),E(v(b(m),O,q),B(m));const M=r(((t,e,n)=>e(n)&&t(n))),I=z,D=Symbol("Placeholder"),L=t=>{let e=0;for(const n of t)n!==D&&e++;return e},U=(t,e)=>{const n=t.length,s=t.slice(),i=e.length;let o=i,r=0;for(;o&&r<n;r++)s[r]===D&&(s[r]=e[i-o],o--);for(r=n;o;r++,o--)s[r]=e[i-o];return s},F=(t,e,n)=>{const s=t.length-e.length-L(n);if(s<1)return t(...U(e,n));{const i=(...s)=>F(t,U(e,n),s);return i.$args_left=s,i}},J=t=>(...e)=>t.length>L(e)?F(t,[],e):t(...e);function G(t){return function(e,...n){return n.length>0?e===D?(t=>function(e){return e===D?t:t(e)})((e=>t(e,n[0]))):t(e,n[0]):n=>t(e,n)}}function H(t){return J(t)}const K=t=>t.length,V=/^(.*?)(8|16|32|64)(Clamped)?Array$/,X=void 0,Y=1/0,Z=t=>typeof t,tt=t=>null===t,et={u:"U",b:"B",n:"N",s:"S",f:"F"},nt=Symbol(),st=t=>{const e=Z(t);return"object"===e?tt(t)?"Null":t.constructor.name:et[e[0]]+e.slice(1)},it=G(((t,e)=>st(e)===t)),ot=G(((t,e)=>t===e)),rt=G(((t,e)=>{const n=st(t);if(ot(n,st(e))&&(ot(n,"Object")||ot(n,"Array")||(s=n,V.test(s)))){if(tt(t)||tt(e))return ot(t,e);if(ot(t,e))return!0;for(const n of[t,e])for(const s in n)if(!(ot(n,e)&&s in t||ot(n,t)&&s in e&&rt(t[s],e[s])))return!1;return!0}var s;return ot(t,e)})),lt=G(((t,e)=>(e.push(t),e))),ct=H(((t,e,n)=>n.reduce(t,e))),ut=J(((t,e,n,s)=>t(s)?e(s):n(s))),at=H(((t,e,n)=>ut(t,e,yt,n))),ht=(...t)=>(...e)=>{let n,s=!0;for(let i=K(t)-1;i>-1;i--)s?(s=!1,n=t[i](...e)):n=n===D?t[i]():t[i](n);return n},dt=G(((t,e)=>e[t])),ft=H(((t,e,n)=>n.slice(t,(t=>"number"==Z(t))(e)?e:Y))),pt=dt(0);ft(1,Y);const gt=G(((t,e)=>e.find(t))),mt=t=>()=>t,yt=t=>t,_t=G(((t,e)=>e.split(t))),wt=mt(!0),bt=mt(!1),kt=G(((t,e)=>ct(((e,n)=>gt((e=>t(n,e)),e)?e:lt(n,e)),[],e)))(rt),St=(t,e,n)=>K(e)?(t=>tt(t)||(t=>t===X)(t))(n)?t:ht((s=>s in n?St(t,ft(1,Y,e),n[s]):t),pt)(e):n,Pt=H(St);Pt(X),ht(ut(rt(nt),bt,wt),Pt(nt));const vt=G(((t,e)=>e.map(t))),{floor:Et}=Math,At="0123456789abcdefghijklmnopqrstuvwxyz",Ct=it("String"),jt=at(Ct,_t("")),Nt=ht((t=>Object.fromEntries(t)),vt(((t,e)=>[t,e])),jt);class Wt{is_str;delim;abc;abclen;c2pos;standard;setABC(t,e=""){if(this.is_str=Ct(t),this.delim=e,!ht(ot(K(n=t)),K,kt,jt)(n))throw new Error("Not all chars are unique!");var n;this.abc=t,this.abclen=K(t),this.standard=!!this.is_str&&At.startsWith(t),this.c2pos=Nt(t)}zip(t){const{abc:e,abclen:n,delim:s}=this;let i="",o=!0;for(;t>0;)i=e[t%n]+(o?"":s)+i,t=Et(t/n),o=!1;return i||"0"}unzip(t){const{standard:e,abclen:n,c2pos:s,delim:i,is_str:o}=this;if("0"===t)return 0;if(e)return parseInt(t,n);const r=o?t:t.split(i),l=K(r);let c=0;for(let t=0;t<l;t++)c+=s[r[t]]*n**(l-t-1);return c}constructor(t,e){e?this.setABC(t,e):this.setABC(t||At+"ABCDEFGHIJKLMNOPQRSTUVWXYZ")}}const $t=new Wt;$t.setABC.bind($t),$t.zip.bind($t),$t.unzip.bind($t);const qt=(()=>{try{return WebSocket||null}catch{return null}})(),Ot=(t,e,n)=>t.addEventListener(e,n),xt=(t,e)=>setTimeout(e,t),zt={data_type:"json",log:()=>null,timer:!1,url:"localhost",timeout:1400,reconnect:2,reconnection_attempts:1/0,max_idle_time:1/0,lazy:!1,socket:null,adapter:(t,e)=>new WebSocket(t,e),encode:(t,e,{server:n})=>JSON.stringify({[n.id_key]:t,[n.data_key]:e}),decode:t=>JSON.parse(t),protocols:[],pipes:[],server:{id_key:"id",data_key:"data"},ping:{interval:55,content:{}}},{random:Qt}=Math,Tt=new Wt,Rt=x([]),Bt=M(_("Number"),I(isNaN)),Mt={_is_ping:!0},It=t=>t&&clearTimeout(t),Dt=t=>{const e=Tt.zip(2147483637*Qt()|0);return e in t?Dt(t):e};class Lt{ws=null;intentionally_closed=!1;reconnect_timeout=null;queue={};onReadyQueue=[];onCloseQueue=[];handlers={open:[],close:[],message:[],error:[],timeout:[]};config={};ping_timer=null;idle_timer=null;get opened(){return 1===this.ws?.readyState}init_flush(){P(O,this.queue)}call(t,...e){for(const n of this.handlers[t])n(...e)}log(t,e=null,n=null){const{config:s}=this;setTimeout((()=>{null===n?s.timer?s.log(t,null,e):s.log(t,e):s.log(t,n,e)}))}resetPing(){const{config:{ping:t},ping_timer:e}=this;t&&(p(e)||clearTimeout(e),this.ping_timer=xt(1e3*t.interval,(async()=>{const{ping_timer:e,opened:n}=this;n?(await this.send(t.content,Mt),this.resetPing()):clearTimeout(e)})))}resetIdle(){const{config:{max_idle_time:t},idle_timer:e}=this;t!==1/0&&(p(e)||clearTimeout(e),this.idle_timer=xt(1e3*t,(()=>this.opened&&this.close())))}initSocket(t){const{queue:e,config:n}=this;this.ws=t,this.onReadyQueue.forEach((t=>t())),this.onReadyQueue.splice(0);const{id_key:s,data_key:i}=n.server;this.call("open",t);for(const n in e)t.send(e[n].msg);null!==this.reconnect_timeout&&(clearInterval(this.reconnect_timeout),this.reconnect_timeout=null),this.resetPing(),this.resetIdle(),Ot(t,"close",(async(...t)=>{this.log("close"),this.ws=null,this.onCloseQueue.forEach(Rt),this.onCloseQueue.splice(0),this.call("close",...t);let{reconnect:e,reconnection_attempts:s}=n;if(Bt(e)){const t=async()=>{if(this.intentionally_closed||!s)return;s--,this.log("reconnect"),p(this.ws)||(this.ws.close(),this.ws=null);const n=await this.connect();p(n)||(this.reconnect_timeout=setTimeout(t,1e3*e))};t()}})),Ot(t,"message",(t=>{try{const e=n.decode(t.data);this.call("message",{...t,data:e});let o=!1;if(_("Object",e)&&s in e){const t=this.queue[e[s]];if(t){const n=t.sent_time?Date.now()-t.sent_time:null;this.log("message",e[i],n),t.ff(e[i]),o=!0}}o||this.log("message-ext",e)}catch(e){console.error(e,`WSP: Decode error. Got: ${t.data}`)}this.resetPing()}))}opening=!1;connect(){return new Promise((t=>{if(this.opened||this.opening)return t(null);this.opening=!0;const e=this.config,n=e.socket||e.adapter(e.url,e.protocols);if(!n||n.readyState>1)return this.opening=!1,this.ws=null,this.log("error","ready() on closing or closed state! status 2."),t(2);const s=T((e=>{this.opening=!1,t(e)}));Ot(n,"error",T((t=>{this.ws=null,this.log("error","status 3. Err: "+t.message),this.call("error",t),s(3)}))),n.readyState?(this.initSocket(n),s(null)):Ot(n,"open",T((()=>{this.log("open"),this.initSocket(n),s(null)})))}))}get socket(){return this.ws}async ready(){return new Promise((t=>{this.config.lazy||this.opened?t():this.onReadyQueue.push(t)}))}on(t,e,n=q,s=!1){const i=t=>n(t)&&e(t);return s?Ot(this.ws,t,i):this.handlers[t].push(i),i}off(t,e,n=!1){if(n)return((t,e,n)=>t.removeEventListener(e,n))(this.ws,t,e);const s=this.handlers[t],i=s.indexOf(e);~i&&s.splice(i,1)}async close(){return new Promise(((t,e)=>{null===this.ws?e("WSP: closing a non-inited socket!"):(this.onCloseQueue.push((()=>{this.init_flush(),t(null)})),this.ws.close(),this.ws=null,this.intentionally_closed=!0)}))}open(){if(!this.opened)return this.intentionally_closed=!1,this.connect()}async prepareMessage(t,e={}){this.log(e._is_ping?"ping":"send",t);const{config:n,queue:s}=this,{pipes:i,server:{data_key:o}}=n,{top:r,_is_ping:l}=e,c=Dt(s);if("object"==typeof r&&r[o])throw new Error(`Attempting to set data key/token via ${e._is_ping?"ping":"send"}() options!`);for(const e of i)t=e(t);const[u,a]=await Promise.all([n.encode(c,t,n),this.connect()]);if(a)throw new Error("ERR while opening connection #"+a);const h=$((()=>delete this.queue[c]));return this.opened&&(xt(0,(()=>this.ws.send(u))),this.resetPing(),l||this.resetIdle()),{id:c,msg:u,timeout:e=>xt(n.timeout,(()=>{c in s&&(this.call("timeout",t),e({"Websocket timeout expired":n.timeout,"for the message":t}),h())})),cleanup:h}}async send(t,e={}){const{id:n,msg:s,timeout:i,cleanup:o}=await this.prepareMessage(t,e),{queue:r,config:l}=this;return new Promise(((t,e)=>{const o=i(e);r[n]={msg:s,data_type:l.data_type,sent_time:l.timer?Date.now():null,ff(e){It(o),t(e)}}})).finally(o)}async*stream(t,e={}){const{id:n,msg:s,timeout:i,cleanup:o}=await this.prepareMessage(t,e),{queue:r,config:l}=this;let c,u=!1,a=null;for(r[n]={msg:s,ff:t=>{c(t),t?.done&&(o(),u=!0)},data_type:l.data_type,sent_time:l.timer?Date.now():null};!u;)yield await new Promise(((t,e)=>{a=i(e),c=t})).catch((t=>o(t))).finally((()=>{It(a),a=null}))}constructor(t={}){this.config=(t=>{if(null===qt&&!("adapter"in t))throw new Error("\n This platform has no native WebSocket implementation.\n Please use 'ws' package as an adapter.\n See https://github.com/houd1ni/WebsocketPromisify/issues/23\n ");const e=Object.assign({},zt,t),n=e.url;if("/"==n[0])try{const t=location.protocol.includes("s:")?"wss":"ws";e.url=`${t}://${location.hostname}:${location.port}${n}`}catch(t){throw new Error("WSP: URL starting with / in non-browser environment!")}return e})(t),this.config.lazy||this.connect()}}exports.WebSocketClient=Lt,exports.default=Lt;
package/dist/bundle.d.ts CHANGED
@@ -4,7 +4,7 @@ declare namespace wsc {
4
4
  interface DataObject {
5
5
  [key: string]: any;
6
6
  }
7
- type WSEvent = "open" | "message" | "close" | "error" | "timeout";
7
+ type WSEvent = "open" | "message" | "message-ext" | "close" | "error" | "timeout" | "reconnect" | "send" | "ping";
8
8
  /** Minimal socket-like interface. */
9
9
  interface Socket {
10
10
  readyState: number;
@@ -58,7 +58,7 @@ declare namespace wsc {
58
58
  sent_time: number | null;
59
59
  }
60
60
  }
61
- declare class WebSocketClient {
61
+ export declare class WebSocketClient {
62
62
  private ws;
63
63
  private intentionally_closed;
64
64
  private reconnect_timeout;
package/dist/bundle.mjs CHANGED
@@ -1 +1 @@
1
- const e=Symbol("Placeholder"),t=t=>{let n=0;for(const s of t)s!==e&&n++;return n},n=(t,n)=>{const s=t.length,o=t.slice(),i=n.length;let r=i,l=0;for(;r&&l<s;l++)o[l]===e&&(o[l]=n[i-r],r--);for(l=s;r;l++,r--)o[l]=n[i-r];return o},s=(e,o,i)=>{const r=e.length-o.length-t(i);if(r<1)return e(...n(o,i));{const t=(...t)=>s(e,n(o,i),t);return t.$args_left=r,t}},o=e=>(...n)=>e.length>t(n)?s(e,[],n):e(...n);function i(t){return function(n,s){const o=n===e,i=arguments.length;if(1===i&&o)throw new Error("Senseless placeholder usage.");return i>1?o?(t=>function(n){return n===e?t:t(n)})((e=>t(e,s))):t(n,s):e=>t(n,e)}}function r(e){return o(e)}const l=void 0,c=1/0,a=e=>typeof e,u=e=>null===e,h={u:"U",b:"B",n:"N",s:"S",f:"F"},f=Symbol(),d=e=>{const t=a(e);return"object"===t?u(e)?"Null":e.constructor.name:h[t[0]]+t.slice(1)},g=e=>e.length,p=i(((e,t)=>e===t)),m=i(((e,t)=>{const n=d(e);if(p(n,d(t))&&(p(n,"Object")||p(n,"Array"))){if(u(e)||u(t))return p(e,t);if(p(e,t))return!0;for(const n of[e,t])for(const s in n)if(!(p(n,t)&&s in e||p(n,e)&&s in t&&m(e[s],t[s])))return!1;return!0}return p(e,t)})),y=i(((e,t)=>(t.push(e),t))),w=r(((e,t,n)=>n.reduce(e,t))),_=o(((e,t,n,s)=>e(s)?t(s):n(s))),b=(...t)=>(...n)=>{let s,o=!0;for(let i=g(t)-1;i>-1;i--)o?(o=!1,s=t[i](...n)):s=s===e?t[i]():t[i](s);return s},S=i(((e,t)=>t[e])),k=r(((e,t,n)=>n.slice(e,(e=>"number"==a(e))(t)?t:c))),P=S(0);k(1,c);const v=i(((e,t)=>t.find(e))),E=e=>()=>e,N=i(((e,t)=>t.split(e))),q=E(!0),A=E(!1),W=i(((e,t)=>w(((t,n)=>v((t=>e(n,t)),t)?t:y(n,t)),[],t)))(m),$=r(((e,t,n)=>g(t)?(e=>u(e)||(e=>e===l)(e))(n)?e:b((s=>s in n?$(e,k(1,c,t),n[s]):e),P)(t):n));$(l),b(_(m(f),A,q),$(f));const j=i(((e,t)=>t.map(e))),{floor:z}=Math,C="0123456789abcdefghijklmnopqrstuvwxyz",Q=b((e=>Object.fromEntries(e)),j(((e,t)=>[e,t])),N(""));class O{abc;abclen;c2pos;standard;setABC(e){if(!b(m(g(t=e)),g,W,N(""))(t))throw new Error("Not all chars are unique!");var t;this.abc=e,this.abclen=e.length,this.standard=C.startsWith(e),this.c2pos=Q(e)}zip(e){const{abc:t,abclen:n}=this;let s="";for(;e>0;)s=t[e%n]+s,e=z(e/n);return s||"0"}unzip(e){const{standard:t,abclen:n,c2pos:s}=this;if(t)return parseInt(e,n);const o=e.length;let i=0;for(let t=0;t<o;t++)i+=s[e[t]]*n**(o-t-1);return i}constructor(e){this.setABC(e||C+"ABCDEFGHIJKLMNOPQRSTUVWXYZ")}}const R=new O;R.setABC.bind(R),R.zip.bind(R),R.unzip.bind(R);const T=(()=>{try{return WebSocket||null}catch{return null}})(),x=(e,t,n)=>e.addEventListener(t,n),B=(e,t)=>setTimeout(t,e),I={data_type:"json",log:()=>null,timer:!1,url:"localhost",timeout:1400,reconnect:2,reconnection_attempts:1/0,max_idle_time:1/0,lazy:!1,socket:null,adapter:(e,t)=>new WebSocket(e,t),encode:(e,t,{server:n})=>JSON.stringify({[n.id_key]:e,[n.data_key]:t}),decode:e=>JSON.parse(e),protocols:[],pipes:[],server:{id_key:"id",data_key:"data"},ping:{interval:55,content:{}}},M=Symbol("Placeholder"),D=e=>{let t=0;for(const n of e)n!==M&&t++;return t},L=(e,t)=>{const n=e.length,s=e.slice(),o=t.length;let i=o,r=0;for(;i&&r<n;r++)s[r]===M&&(s[r]=t[o-i],i--);for(r=n;i;r++,i--)s[r]=t[o-i];return s},U=(e,t,n)=>{const s=e.length-t.length-D(n);if(s<1)return e(...L(t,n));{const o=(...s)=>U(e,L(t,n),s);return o.$args_left=s,o}},F=e=>(...t)=>e.length>D(t)?U(e,[],t):e(...t);function J(e){return function(t,n){const s=t===M,o=arguments.length;if(1===o&&s)throw new Error("Senseless placeholder usage.");return o>1?s?(e=>function(t){return t===M?e:e(t)})((t=>e(t,n))):e(t,n):n=>e(t,n)}}function G(e){return F(e)}const H=/^(.*?)(8|16|32|64)(Clamped)?Array$/,K=void 0,V=1/0,X=e=>typeof e,Y=e=>null===e,Z=e=>"number"==X(e);const ee=e=>Y(e)||(e=>e===K)(e),te={u:"U",b:"B",n:"N",s:"S",f:"F"},ne=Symbol(),se=e=>{const t=X(e);return"object"===t?Y(e)?"Null":e.constructor.name:te[t[0]]+t.slice(1)},oe=J(((e,t)=>se(t)===e)),ie=e=>e.length,re=J(((e,t)=>e===t)),le=J(((e,t)=>{const n=se(e);if(re(n,se(t))&&(re(n,"Object")||re(n,"Array")||(e=>H.test(e))(n))){if(Y(e)||Y(t))return re(e,t);if(re(e,t))return!0;for(const n of[e,t])for(const s in n)if(!(re(n,t)&&s in e||re(n,e)&&s in t&&le(e[s],t[s])))return!1;return!0}return re(e,t)})),ce=J(((e,t)=>(t.push(e),t))),ae=G(((e,t,n)=>n.reduce(e,t))),ue=J(((e,t)=>{const n=(e=>Array.isArray(e))(t);let s,o;n&&(s=0,o=[]);for(let s in t)e(t[s],s)||(n?o.push(+s):delete t[s]);if(n)for(const e of o)t.splice(e-s++,1);return t})),he=F(((e,t,n,s)=>e(s)?t(s):n(s))),fe=(...e)=>(...t)=>{let n,s=!0;for(let o=ie(e)-1;o>-1;o--)s?(s=!1,n=e[o](...t)):n=n===M?e[o]():e[o](n);return n},de=J(((e,t)=>t[e])),ge=G(((e,t,n)=>n.slice(e,Z(t)?t:V))),pe=de(0);ge(1,V);const me=J(((e,t)=>t.find(e))),ye=e=>()=>e,we=J(((e,t)=>(e(t),t))),_e=ye(!0),be=ye(!1),Se=J(((e,t)=>t(...e))),ke=e=>(...t)=>{const n=e(...t),s=function(e){return"function"===X(e)}(n);return!s||s&&n.$args_left<=0?(e=>!e)(n):ke(n)},Pe=J(((e,t)=>ae(((t,n)=>me((t=>e(n,t)),t)?t:ce(n,t)),[],t)));Pe(le);const ve=e=>{let t,n=!1;return function(...s){return n?t:(n=!0,t=e(...s))}},Ee=G(((e,t,n)=>ie(t)?ee(n)?e:fe((s=>s in n?Ee(e,ge(1,V,t),n[s]):e),pe)(t):n));Ee(K),fe(he(le(ne),be,_e),Ee(ne));const Ne=G(((e,t,n)=>t(n)&&e(n))),qe=ke,{random:Ae}=Math,We=new O,$e=Se([]),je=Ne(oe("Number"),qe(isNaN)),ze={_is_ping:!0},Ce=e=>e&&clearTimeout(e),Qe=e=>{const t=We.zip(2147483637*Ae()|0);return t in e?Qe(e):t};class Oe{ws=null;intentionally_closed=!1;reconnect_timeout=null;queue={};onReadyQueue=[];onCloseQueue=[];handlers={open:[],close:[],message:[],error:[],timeout:[]};config={};ping_timer=null;idle_timer=null;get opened(){return 1===this.ws?.readyState}init_flush(){ue(be,this.queue)}call(e,...t){for(const n of this.handlers[e])n(...t)}log(e,t=null,n=null){const{config:s}=this;null===n?s.timer?s.log(e,null,t):s.log(e,t):s.log(e,n,t)}resetPing(){const{config:{ping:e},ping_timer:t}=this;e&&(ee(t)||clearTimeout(t),this.ping_timer=B(1e3*e.interval,(async()=>{const{ping_timer:t,opened:n}=this;n?(await this.send(e.content,ze),this.resetPing()):clearTimeout(t)})))}resetIdle(){const{config:{max_idle_time:e},idle_timer:t}=this;e!==1/0&&(ee(t)||clearTimeout(t),this.idle_timer=B(1e3*e,(()=>this.opened&&this.close())))}initSocket(e){const{queue:t,config:n}=this;this.ws=e,this.onReadyQueue.forEach((e=>e())),this.onReadyQueue.splice(0);const{id_key:s,data_key:o}=n.server;this.call("open",e);for(const n in t)e.send(t[n].msg);null!==this.reconnect_timeout&&(clearInterval(this.reconnect_timeout),this.reconnect_timeout=null),this.resetPing(),this.resetIdle(),x(e,"close",(async(...e)=>{this.log("close"),this.ws=null,this.onCloseQueue.forEach($e),this.onCloseQueue.splice(0),this.call("close",...e);let{reconnect:t,reconnection_attempts:s}=n;if(je(t)){const e=async()=>{if(this.intentionally_closed||!s)return;s--,this.log("reconnect"),ee(this.ws)||(this.ws.close(),this.ws=null);const n=await this.connect();ee(n)||(this.reconnect_timeout=setTimeout(e,1e3*t))};e()}})),x(e,"message",(e=>{try{const t=n.decode(e.data);if(this.call("message",{...e,data:t}),s in t){const e=this.queue[t[s]];if(e){const n=e.sent_time?Date.now()-e.sent_time:null;this.log("message",t[o],n),e.ff(t[o])}}}catch(t){console.error(t,`WSP: Decode error. Got: ${e.data}`)}this.resetPing()}))}opening=!1;connect(){return new Promise((e=>{if(this.opened||this.opening)return e(null);this.opening=!0;const t=this.config,n=t.socket||t.adapter(t.url,t.protocols);if(!n||n.readyState>1)return this.opening=!1,this.ws=null,this.log("error","ready() on closing or closed state! status 2."),e(2);const s=ve((t=>{this.opening=!1,e(t)}));x(n,"error",ve((e=>{this.ws=null,this.log("error","status 3. Err: "+e.message),this.call("error",e),s(3)}))),n.readyState?(this.initSocket(n),s(null)):x(n,"open",ve((()=>{this.log("open"),this.initSocket(n),s(null)})))}))}get socket(){return this.ws}async ready(){return new Promise((e=>{this.config.lazy||this.opened?e():this.onReadyQueue.push(e)}))}on(e,t,n=_e,s=!1){const o=e=>n(e)&&t(e);return s?x(this.ws,e,o):this.handlers[e].push(o),o}off(e,t,n=!1){if(n)return((e,t,n)=>e.removeEventListener(t,n))(this.ws,e,t);const s=this.handlers[e],o=s.indexOf(t);~o&&s.splice(o,1)}async close(){return new Promise(((e,t)=>{null===this.ws?t("WSP: closing a non-inited socket!"):(this.onCloseQueue.push((()=>{this.init_flush(),e(null)})),this.ws.close(),this.ws=null,this.intentionally_closed=!0)}))}open(){if(!this.opened)return this.intentionally_closed=!1,this.connect()}async prepareMessage(e,t={}){this.log(t._is_ping?"ping":"send",e);const{config:n,queue:s}=this,{pipes:o,server:{data_key:i}}=n,{top:r,_is_ping:l}=t,c=Qe(s);if("object"==typeof r&&r[i])throw new Error(`Attempting to set data key/token via ${t._is_ping?"ping":"send"}() options!`);for(const t of o)e=t(e);const[a,u]=await Promise.all([n.encode(c,e,n),this.connect()]);if(u)throw new Error("ERR while opening connection #"+u);this.opened&&(this.ws.send(a),this.resetPing(),l||this.resetIdle());const h=we((()=>delete this.queue[c]));return{message_id:c,msg:a,timeout:t=>B(n.timeout,(()=>{c in s&&(this.call("timeout",e),t({"Websocket timeout expired":n.timeout,"for the message":e}),h())})),cleanup:h}}async send(e,t={}){const{message_id:n,msg:s,timeout:o,cleanup:i}=await this.prepareMessage(e,t),{queue:r,config:l}=this;return new Promise(((e,t)=>{const i=o(t);r[n]={msg:s,data_type:l.data_type,sent_time:l.timer?Date.now():null,ff(t){Ce(i),e(t)}}})).finally(i)}async*stream(e,t={}){const{message_id:n,msg:s,timeout:o,cleanup:i}=await this.prepareMessage(e,t),{queue:r,config:l}=this;let c,a=!1,u=null;for(r[n]={msg:s,ff:e=>{c(e),e?.done&&(i(),a=!0)},data_type:l.data_type,sent_time:l.timer?Date.now():null};!a;)yield await new Promise(((e,t)=>{u=o(t),c=e})).catch((e=>i(e))).finally((()=>{Ce(u),u=null}))}constructor(e={}){this.config=(e=>{if(null===T&&!("adapter"in e))throw new Error("\n This platform has no native WebSocket implementation.\n Please use 'ws' package as an adapter.\n See https://github.com/houd1ni/WebsocketPromisify/issues/23\n ");const t=Object.assign({},I,e),n=t.url;if("/"==n[0])try{const e=location.protocol.includes("s:")?"wss":"ws";t.url=`${e}://${location.hostname}:${location.port}${n}`}catch(e){throw new Error("WSP: URL starting with / in non-browser environment!")}return t})(e),this.config.lazy||this.connect()}}export{Oe as default};
1
+ const t=Symbol("Placeholder"),e=e=>{let n=0;for(const s of e)s!==t&&n++;return n},n=(e,n)=>{const s=e.length,i=e.slice(),o=n.length;let r=o,l=0;for(;r&&l<s;l++)i[l]===t&&(i[l]=n[o-r],r--);for(l=s;r;l++,r--)i[l]=n[o-r];return i},s=(t,i,o)=>{const r=t.length-i.length-e(o);if(r<1)return t(...n(i,o));{const e=(...e)=>s(t,n(i,o),e);return e.$args_left=r,e}},i=t=>(...n)=>t.length>e(n)?s(t,[],n):t(...n);function o(e){return function(n,...s){return s.length>0?n===t?(e=>function(n){return n===t?e:e(n)})((t=>e(t,s[0]))):e(n,s[0]):t=>e(n,t)}}function r(t){return i(t)}const l=t=>t.length,c=/^(.*?)(8|16|32|64)(Clamped)?Array$/,a=void 0,u=1/0,h=t=>typeof t,f=t=>null===t,d=t=>"number"==h(t);const p=t=>f(t)||(t=>t===a)(t),g={u:"U",b:"B",n:"N",s:"S",f:"F"},m=Symbol(),y=t=>{const e=h(t);return"object"===e?f(t)?"Null":t.constructor.name:g[e[0]]+e.slice(1)},_=o(((t,e)=>y(e)===t)),w=o(((t,e)=>t===e)),b=o(((t,e)=>{const n=y(t);if(w(n,y(e))&&(w(n,"Object")||w(n,"Array")||(t=>c.test(t))(n))){if(f(t)||f(e))return w(t,e);if(w(t,e))return!0;for(const n of[t,e])for(const s in n)if(!(w(n,e)&&s in t||w(n,t)&&s in e&&b(t[s],e[s])))return!1;return!0}return w(t,e)})),k=o(((t,e)=>(e.push(t),e))),S=r(((t,e,n)=>n.reduce(t,e))),P=o(((t,e)=>{const n=(t=>Array.isArray(t))(e);let s,i;n&&(s=0,i=[]);for(let s in e)t(e[s],s)||(n?i.push(+s):delete e[s]);if(n)for(const t of i)e.splice(t-s++,1);return e})),v=i(((t,e,n,s)=>t(s)?e(s):n(s))),E=(...e)=>(...n)=>{let s,i=!0;for(let o=l(e)-1;o>-1;o--)i?(i=!1,s=e[o](...n)):s=s===t?e[o]():e[o](s);return s},A=o(((t,e)=>e[t])),C=r(((t,e,n)=>n.slice(t,d(e)?e:u))),N=A(0);C(1,u);const $=o(((t,e)=>e.find(t))),j=t=>()=>t,q=o(((t,e)=>(t(e),e))),W=j(!0),z=j(!1),O=o(((t,e)=>e(...t))),Q=t=>(...e)=>{const n=t(...e),s=function(t){return"function"===h(t)}(n);return s&&n.$args_left?Q(n):(t=>!t)(n)},T=o(((t,e)=>S(((e,n)=>$((e=>t(n,e)),e)?e:k(n,e)),[],e)));T(b);const R=t=>{let e,n=!1;return function(...s){return n?e:(n=!0,e=t(...s))}},x=(t,e,n)=>l(e)?p(n)?t:E((s=>s in n?x(t,C(1,u,e),n[s]):t),N)(e):n,B=r(x);B(a),E(v(b(m),z,W),B(m));const I=r(((t,e,n)=>e(n)&&t(n))),M=Q,D=Symbol("Placeholder"),L=t=>{let e=0;for(const n of t)n!==D&&e++;return e},U=(t,e)=>{const n=t.length,s=t.slice(),i=e.length;let o=i,r=0;for(;o&&r<n;r++)s[r]===D&&(s[r]=e[i-o],o--);for(r=n;o;r++,o--)s[r]=e[i-o];return s},F=(t,e,n)=>{const s=t.length-e.length-L(n);if(s<1)return t(...U(e,n));{const i=(...s)=>F(t,U(e,n),s);return i.$args_left=s,i}},J=t=>(...e)=>t.length>L(e)?F(t,[],e):t(...e);function G(t){return function(e,...n){return n.length>0?e===D?(t=>function(e){return e===D?t:t(e)})((e=>t(e,n[0]))):t(e,n[0]):n=>t(e,n)}}function H(t){return J(t)}const K=t=>t.length,V=/^(.*?)(8|16|32|64)(Clamped)?Array$/,X=void 0,Y=1/0,Z=t=>typeof t,tt=t=>null===t,et={u:"U",b:"B",n:"N",s:"S",f:"F"},nt=Symbol(),st=t=>{const e=Z(t);return"object"===e?tt(t)?"Null":t.constructor.name:et[e[0]]+e.slice(1)},it=G(((t,e)=>st(e)===t)),ot=G(((t,e)=>t===e)),rt=G(((t,e)=>{const n=st(t);if(ot(n,st(e))&&(ot(n,"Object")||ot(n,"Array")||(s=n,V.test(s)))){if(tt(t)||tt(e))return ot(t,e);if(ot(t,e))return!0;for(const n of[t,e])for(const s in n)if(!(ot(n,e)&&s in t||ot(n,t)&&s in e&&rt(t[s],e[s])))return!1;return!0}var s;return ot(t,e)})),lt=G(((t,e)=>(e.push(t),e))),ct=H(((t,e,n)=>n.reduce(t,e))),at=J(((t,e,n,s)=>t(s)?e(s):n(s))),ut=H(((t,e,n)=>at(t,e,yt,n))),ht=(...t)=>(...e)=>{let n,s=!0;for(let i=K(t)-1;i>-1;i--)s?(s=!1,n=t[i](...e)):n=n===D?t[i]():t[i](n);return n},ft=G(((t,e)=>e[t])),dt=H(((t,e,n)=>n.slice(t,(t=>"number"==Z(t))(e)?e:Y))),pt=ft(0);dt(1,Y);const gt=G(((t,e)=>e.find(t))),mt=t=>()=>t,yt=t=>t,_t=G(((t,e)=>e.split(t))),wt=mt(!0),bt=mt(!1),kt=G(((t,e)=>ct(((e,n)=>gt((e=>t(n,e)),e)?e:lt(n,e)),[],e)))(rt),St=(t,e,n)=>K(e)?(t=>tt(t)||(t=>t===X)(t))(n)?t:ht((s=>s in n?St(t,dt(1,Y,e),n[s]):t),pt)(e):n,Pt=H(St);Pt(X),ht(at(rt(nt),bt,wt),Pt(nt));const vt=G(((t,e)=>e.map(t))),{floor:Et}=Math,At="0123456789abcdefghijklmnopqrstuvwxyz",Ct=it("String"),Nt=ut(Ct,_t("")),$t=ht((t=>Object.fromEntries(t)),vt(((t,e)=>[t,e])),Nt);class jt{is_str;delim;abc;abclen;c2pos;standard;setABC(t,e=""){if(this.is_str=Ct(t),this.delim=e,!ht(ot(K(n=t)),K,kt,Nt)(n))throw new Error("Not all chars are unique!");var n;this.abc=t,this.abclen=K(t),this.standard=!!this.is_str&&At.startsWith(t),this.c2pos=$t(t)}zip(t){const{abc:e,abclen:n,delim:s}=this;let i="",o=!0;for(;t>0;)i=e[t%n]+(o?"":s)+i,t=Et(t/n),o=!1;return i||"0"}unzip(t){const{standard:e,abclen:n,c2pos:s,delim:i,is_str:o}=this;if("0"===t)return 0;if(e)return parseInt(t,n);const r=o?t:t.split(i),l=K(r);let c=0;for(let t=0;t<l;t++)c+=s[r[t]]*n**(l-t-1);return c}constructor(t,e){e?this.setABC(t,e):this.setABC(t||At+"ABCDEFGHIJKLMNOPQRSTUVWXYZ")}}const qt=new jt;qt.setABC.bind(qt),qt.zip.bind(qt),qt.unzip.bind(qt);const Wt=(()=>{try{return WebSocket||null}catch{return null}})(),zt=(t,e,n)=>t.addEventListener(e,n),Ot=(t,e)=>setTimeout(e,t),Qt={data_type:"json",log:()=>null,timer:!1,url:"localhost",timeout:1400,reconnect:2,reconnection_attempts:1/0,max_idle_time:1/0,lazy:!1,socket:null,adapter:(t,e)=>new WebSocket(t,e),encode:(t,e,{server:n})=>JSON.stringify({[n.id_key]:t,[n.data_key]:e}),decode:t=>JSON.parse(t),protocols:[],pipes:[],server:{id_key:"id",data_key:"data"},ping:{interval:55,content:{}}},{random:Tt}=Math,Rt=new jt,xt=O([]),Bt=I(_("Number"),M(isNaN)),It={_is_ping:!0},Mt=t=>t&&clearTimeout(t),Dt=t=>{const e=Rt.zip(2147483637*Tt()|0);return e in t?Dt(t):e};class Lt{ws=null;intentionally_closed=!1;reconnect_timeout=null;queue={};onReadyQueue=[];onCloseQueue=[];handlers={open:[],close:[],message:[],error:[],timeout:[]};config={};ping_timer=null;idle_timer=null;get opened(){return 1===this.ws?.readyState}init_flush(){P(z,this.queue)}call(t,...e){for(const n of this.handlers[t])n(...e)}log(t,e=null,n=null){const{config:s}=this;setTimeout((()=>{null===n?s.timer?s.log(t,null,e):s.log(t,e):s.log(t,n,e)}))}resetPing(){const{config:{ping:t},ping_timer:e}=this;t&&(p(e)||clearTimeout(e),this.ping_timer=Ot(1e3*t.interval,(async()=>{const{ping_timer:e,opened:n}=this;n?(await this.send(t.content,It),this.resetPing()):clearTimeout(e)})))}resetIdle(){const{config:{max_idle_time:t},idle_timer:e}=this;t!==1/0&&(p(e)||clearTimeout(e),this.idle_timer=Ot(1e3*t,(()=>this.opened&&this.close())))}initSocket(t){const{queue:e,config:n}=this;this.ws=t,this.onReadyQueue.forEach((t=>t())),this.onReadyQueue.splice(0);const{id_key:s,data_key:i}=n.server;this.call("open",t);for(const n in e)t.send(e[n].msg);null!==this.reconnect_timeout&&(clearInterval(this.reconnect_timeout),this.reconnect_timeout=null),this.resetPing(),this.resetIdle(),zt(t,"close",(async(...t)=>{this.log("close"),this.ws=null,this.onCloseQueue.forEach(xt),this.onCloseQueue.splice(0),this.call("close",...t);let{reconnect:e,reconnection_attempts:s}=n;if(Bt(e)){const t=async()=>{if(this.intentionally_closed||!s)return;s--,this.log("reconnect"),p(this.ws)||(this.ws.close(),this.ws=null);const n=await this.connect();p(n)||(this.reconnect_timeout=setTimeout(t,1e3*e))};t()}})),zt(t,"message",(t=>{try{const e=n.decode(t.data);this.call("message",{...t,data:e});let o=!1;if(_("Object",e)&&s in e){const t=this.queue[e[s]];if(t){const n=t.sent_time?Date.now()-t.sent_time:null;this.log("message",e[i],n),t.ff(e[i]),o=!0}}o||this.log("message-ext",e)}catch(e){console.error(e,`WSP: Decode error. Got: ${t.data}`)}this.resetPing()}))}opening=!1;connect(){return new Promise((t=>{if(this.opened||this.opening)return t(null);this.opening=!0;const e=this.config,n=e.socket||e.adapter(e.url,e.protocols);if(!n||n.readyState>1)return this.opening=!1,this.ws=null,this.log("error","ready() on closing or closed state! status 2."),t(2);const s=R((e=>{this.opening=!1,t(e)}));zt(n,"error",R((t=>{this.ws=null,this.log("error","status 3. Err: "+t.message),this.call("error",t),s(3)}))),n.readyState?(this.initSocket(n),s(null)):zt(n,"open",R((()=>{this.log("open"),this.initSocket(n),s(null)})))}))}get socket(){return this.ws}async ready(){return new Promise((t=>{this.config.lazy||this.opened?t():this.onReadyQueue.push(t)}))}on(t,e,n=W,s=!1){const i=t=>n(t)&&e(t);return s?zt(this.ws,t,i):this.handlers[t].push(i),i}off(t,e,n=!1){if(n)return((t,e,n)=>t.removeEventListener(e,n))(this.ws,t,e);const s=this.handlers[t],i=s.indexOf(e);~i&&s.splice(i,1)}async close(){return new Promise(((t,e)=>{null===this.ws?e("WSP: closing a non-inited socket!"):(this.onCloseQueue.push((()=>{this.init_flush(),t(null)})),this.ws.close(),this.ws=null,this.intentionally_closed=!0)}))}open(){if(!this.opened)return this.intentionally_closed=!1,this.connect()}async prepareMessage(t,e={}){this.log(e._is_ping?"ping":"send",t);const{config:n,queue:s}=this,{pipes:i,server:{data_key:o}}=n,{top:r,_is_ping:l}=e,c=Dt(s);if("object"==typeof r&&r[o])throw new Error(`Attempting to set data key/token via ${e._is_ping?"ping":"send"}() options!`);for(const e of i)t=e(t);const[a,u]=await Promise.all([n.encode(c,t,n),this.connect()]);if(u)throw new Error("ERR while opening connection #"+u);const h=q((()=>delete this.queue[c]));return this.opened&&(Ot(0,(()=>this.ws.send(a))),this.resetPing(),l||this.resetIdle()),{id:c,msg:a,timeout:e=>Ot(n.timeout,(()=>{c in s&&(this.call("timeout",t),e({"Websocket timeout expired":n.timeout,"for the message":t}),h())})),cleanup:h}}async send(t,e={}){const{id:n,msg:s,timeout:i,cleanup:o}=await this.prepareMessage(t,e),{queue:r,config:l}=this;return new Promise(((t,e)=>{const o=i(e);r[n]={msg:s,data_type:l.data_type,sent_time:l.timer?Date.now():null,ff(e){Mt(o),t(e)}}})).finally(o)}async*stream(t,e={}){const{id:n,msg:s,timeout:i,cleanup:o}=await this.prepareMessage(t,e),{queue:r,config:l}=this;let c,a=!1,u=null;for(r[n]={msg:s,ff:t=>{c(t),t?.done&&(o(),a=!0)},data_type:l.data_type,sent_time:l.timer?Date.now():null};!a;)yield await new Promise(((t,e)=>{u=i(e),c=t})).catch((t=>o(t))).finally((()=>{Mt(u),u=null}))}constructor(t={}){this.config=(t=>{if(null===Wt&&!("adapter"in t))throw new Error("\n This platform has no native WebSocket implementation.\n Please use 'ws' package as an adapter.\n See https://github.com/houd1ni/WebsocketPromisify/issues/23\n ");const e=Object.assign({},Qt,t),n=e.url;if("/"==n[0])try{const t=location.protocol.includes("s:")?"wss":"ws";e.url=`${t}://${location.hostname}:${location.port}${n}`}catch(t){throw new Error("WSP: URL starting with / in non-browser environment!")}return e})(t),this.config.lazy||this.connect()}}export{Lt as WebSocketClient,Lt as default};
package/package.json CHANGED
@@ -41,7 +41,7 @@
41
41
  "prod": "npm run gentypes && npm run prod:es && npm run prod:cjs",
42
42
  "all": "npm run dev && npm run prod"
43
43
  },
44
- "version": "2.9.4",
44
+ "version": "2.10.0",
45
45
  "type": "module",
46
46
  "exports": {
47
47
  ".": {
@@ -52,28 +52,28 @@
52
52
  "./src": "./src/*"
53
53
  },
54
54
  "devDependencies": {
55
- "@rollup/plugin-commonjs": "^29.0.0",
55
+ "@rollup/plugin-commonjs": "^29.0.2",
56
56
  "@rollup/plugin-node-resolve": "^16.0.3",
57
57
  "@rollup/plugin-replace": "^6.0.3",
58
- "@rollup/plugin-terser": "^0.4.4",
58
+ "@rollup/plugin-terser": "^1.0.0",
59
59
  "@types/express": "^5.0.6",
60
- "@types/node": "^25.0.3",
60
+ "@types/node": "^25.4.0",
61
61
  "@types/ws": "^8.18.1",
62
- "codecov": "^3.6.2",
62
+ "codecov": "^3.6.3",
63
63
  "cross-env": "^10.1.0",
64
64
  "dts-bundle-generator": "^9.5.1",
65
- "nyc": "^17.1.0",
66
- "rollup": "^4.54.0",
65
+ "nyc": "^18.0.0",
66
+ "rollup": "^4.59.0",
67
67
  "rollup-plugin-typescript2": "^0.36.0",
68
68
  "ts-node": "^10.9.2",
69
69
  "tsx": "^4.21.0",
70
70
  "typescript": "^5.9.3",
71
71
  "uvu": "^0.5.6",
72
- "ws": "^8.18.3"
72
+ "ws": "^8.19.0"
73
73
  },
74
74
  "types": "./dist/bundle.d.ts",
75
75
  "dependencies": {
76
- "pepka": "^1.6.12",
77
- "zipnum": "^2.0.0"
76
+ "pepka": "^1.6.23",
77
+ "zipnum": "^2.1.3"
78
78
  }
79
79
  }
package/rollup.config.js CHANGED
@@ -1,8 +1,8 @@
1
1
  import commonjs from '@rollup/plugin-commonjs'
2
2
  import resolve from '@rollup/plugin-node-resolve'
3
- import typescript from 'rollup-plugin-typescript2'
4
- import terser from '@rollup/plugin-terser'
5
3
  import replace from '@rollup/plugin-replace'
4
+ import terser from '@rollup/plugin-terser'
5
+ import typescript from 'rollup-plugin-typescript2'
6
6
  import tsc from 'typescript'
7
7
 
8
8
  export default {
@@ -32,9 +32,7 @@ export default {
32
32
  process.env.NODE_ENV!='development' && terser(),
33
33
  replace({
34
34
  preventAssignment: true,
35
- values: {
36
- 'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV)
37
- }
35
+ values: { 'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV) }
38
36
  })
39
37
  ]
40
38
  }
package/src/WSC.ts CHANGED
@@ -1,8 +1,8 @@
1
- import './types'
1
+ import { AnyFunc, AnyObject, both, callWith, F, isNil, notf, once, qfilter, T, tap, typeIs } from 'pepka'
2
2
  import { Zipnum } from 'zipnum'
3
- import { add_event, rm_event, sett } from './utils'
4
3
  import { processConfig } from './config'
5
- import { AnyFunc, AnyObject, both, callWith, F, identity, isNil, notf, once, qfilter, T, tap, typeIs } from 'pepka'
4
+ import './types'
5
+ import { add_event, rm_event, sett } from './utils'
6
6
 
7
7
  const MAX_32 = 2**31 - 1
8
8
  const { random } = Math
@@ -25,7 +25,7 @@ const genid = (q: AnyObject) => {
25
25
  return id in q ? genid(q) : id
26
26
  }
27
27
 
28
- class WebSocketClient {
28
+ export class WebSocketClient {
29
29
  private ws: wsc.Socket|null = null
30
30
  private intentionally_closed = false
31
31
  private reconnect_timeout: NodeJS.Timeout|null = null
@@ -45,16 +45,16 @@ class WebSocketClient {
45
45
  private call(event_name: wsc.WSEvent, ...args: any[]) {
46
46
  for(const h of this.handlers[event_name]) h(...args)
47
47
  }
48
-
49
- private log(event: string, message: any = null, time: number|null = null): void {
48
+ private log(event: wsc.WSEvent, message: any = null, time: number|null = null): void {
50
49
  const {config} = this
51
- if(time === null)
52
- if(config.timer) config.log(event, null, message)
53
- else config.log(event, message)
54
- else
55
- config.log(event, time, message)
50
+ setTimeout(() => {
51
+ if(time === null)
52
+ if(config.timer) config.log(event, null, message)
53
+ else config.log(event, message)
54
+ else
55
+ config.log(event, time, message)
56
+ })
56
57
  }
57
-
58
58
  private resetPing() {
59
59
  const {config: {ping}, ping_timer} = this
60
60
  if(ping) {
@@ -70,7 +70,7 @@ class WebSocketClient {
70
70
  }
71
71
  }
72
72
 
73
- // // FIXME: Make some version where it could work fater (for streaming).
73
+ // FIXME: Make some version where it could work faster (for streaming).
74
74
  private resetIdle() {
75
75
  const {config: {max_idle_time: time}, idle_timer} = this
76
76
  if(time!==Infinity) {
@@ -123,7 +123,8 @@ class WebSocketClient {
123
123
  try {
124
124
  const data = config.decode(e.data)
125
125
  this.call('message', {...e, data})
126
- if(id_key in data) {
126
+ let internal = false
127
+ if(typeIs('Object', data) && id_key in data) {
127
128
  const q = this.queue[data[id_key]]
128
129
  if(q) {
129
130
  // Debug, Log.
@@ -131,15 +132,16 @@ class WebSocketClient {
131
132
  this.log('message', data[data_key], time)
132
133
  // Play.
133
134
  q.ff(data[data_key])
135
+ internal = true
134
136
  }
135
137
  }
138
+ if(!internal) this.log('message-ext', data)
136
139
  } catch (err) {
137
140
  console.error(err, `WSP: Decode error. Got: ${e.data}`)
138
141
  }
139
142
  this.resetPing()
140
143
  })
141
144
  }
142
-
143
145
  private opening = false
144
146
  private connect() { // returns status if won't open or null if ok.
145
147
  return new Promise<null|number>((ff) => {
@@ -177,8 +179,7 @@ class WebSocketClient {
177
179
  public get socket() { return this.ws }
178
180
  public async ready() {
179
181
  return new Promise<void>((ff) => {
180
- if(this.config.lazy) ff() // FIXME: (possibly) breaking change ?? At least minor ver bump with a notice!!!
181
- else if(this.opened) ff()
182
+ if(this.config.lazy || this.opened) ff() // FIXME: (possibly) breaking change ?? At least minor ver bump with a notice!!!
182
183
  else this.onReadyQueue.push(ff)
183
184
  })
184
185
  }
@@ -204,7 +205,6 @@ class WebSocketClient {
204
205
  const i = handlers.indexOf(handler)
205
206
  if(~i) handlers.splice(i, 1)
206
207
  }
207
-
208
208
  public async close(): wsc.AsyncErrCode {
209
209
  return new Promise((ff, rj) => {
210
210
  if(this.ws === null) {
@@ -220,17 +220,15 @@ class WebSocketClient {
220
220
  }
221
221
  })
222
222
  }
223
-
224
223
  public open() {
225
224
  if(!this.opened) {
226
225
  this.intentionally_closed = false
227
226
  return this.connect()
228
227
  }
229
228
  }
230
-
231
229
  // TODO: Сделать сэттер элементов конфигурации чтобы двигать таймауты.
232
230
  // И эвент, когда схема наша, а соответствующего элемента очереди не ма.
233
- // Или добавить флажок к эвенту 'message'.
231
+ // Или добавить флажок к эвенту 'message'.F
234
232
  // И событие 'line' со значением on: boolean. Критерии?
235
233
  private async prepareMessage<RequestDataType = any>(
236
234
  message_data: RequestDataType,
@@ -252,11 +250,6 @@ class WebSocketClient {
252
250
  this.connect()
253
251
  ])
254
252
  if(err) throw new Error('ERR while opening connection #'+err)
255
- if(this.opened) {
256
- this.ws!.send(msg)
257
- this.resetPing()
258
- if(!_is_ping) this.resetIdle()
259
- }
260
253
  const cleanup = tap(() => delete this.queue[id])
261
254
  const timeout = (rj: AnyFunc) => sett(config.timeout, () => {
262
255
  if(id in queue) {
@@ -265,9 +258,13 @@ class WebSocketClient {
265
258
  cleanup()
266
259
  }
267
260
  })
268
- return { message_id: id, msg, timeout, cleanup }
261
+ if(this.opened) {
262
+ sett(0, () => this.ws!.send(msg))
263
+ this.resetPing()
264
+ if(!_is_ping) this.resetIdle()
265
+ }
266
+ return { id, msg, timeout, cleanup }
269
267
  }
270
-
271
268
  /** .send(your_data) wraps request to server with {id: `hash`, data: `actually your data`},
272
269
  returns a Promise that will be rejected after a timeout or
273
270
  resolved if server returns the same signature: {id: `same_hash`, data: `response data`}.
@@ -276,12 +273,11 @@ class WebSocketClient {
276
273
  message_data: RequestDataType,
277
274
  opts = <wsc.SendOptions>{}
278
275
  ): Promise<ResponseDataType> {
279
- const {message_id, msg, timeout, cleanup} = await this.prepareMessage(message_data, opts)
276
+ const {id, msg, timeout, cleanup} = await this.prepareMessage(message_data, opts)
280
277
  const {queue, config} = this
281
-
282
278
  return new Promise<ResponseDataType>((ff, rj) => {
283
279
  const to = timeout(rj)
284
- queue[message_id] = {
280
+ queue[id] = {
285
281
  msg,
286
282
  data_type: config.data_type,
287
283
  sent_time: config.timer ? Date.now() : null,
@@ -292,15 +288,15 @@ class WebSocketClient {
292
288
  }
293
289
  }).finally(cleanup)
294
290
  }
295
-
291
+ // FIXME: rejects into ff somehow.
296
292
  public async *stream<RequestDataType = any, ResponseDataType = any>(
297
293
  message_data: RequestDataType,
298
294
  opts = <wsc.SendOptions>{}
299
295
  ): AsyncGenerator<ResponseDataType, void, unknown> {
300
- const {message_id, msg, timeout, cleanup} = await this.prepareMessage(message_data, opts)
296
+ const {id, msg, timeout, cleanup} = await this.prepareMessage(message_data, opts)
301
297
  const {queue, config} = this
302
298
  let done = false, fulfill: AnyFunc, to: NodeJS.Timeout|null = null
303
- queue[message_id] = {
299
+ queue[id] = {
304
300
  msg,
305
301
  ff: (msg: ResponseDataType&{done?: boolean}) => {
306
302
  fulfill(msg)
@@ -313,7 +309,6 @@ class WebSocketClient {
313
309
  to=timeout(rj); fulfill=ff
314
310
  }).catch((e) => cleanup(e)).finally(() => {clearTO(to); to=null})
315
311
  }
316
-
317
312
  // TODO: Add .on handlers to config!
318
313
  constructor(user_config: wsc.UserConfig = {}) {
319
314
  this.config = processConfig(user_config)
package/src/types.ts CHANGED
@@ -4,7 +4,7 @@ declare namespace wsc {
4
4
  [key: string]: any
5
5
  }
6
6
 
7
- export type WSEvent = 'open' | 'message' | 'close' | 'error' | 'timeout'
7
+ export type WSEvent = 'open' | 'message' | 'message-ext' | 'close' | 'error' | 'timeout' | 'reconnect' | 'send' | 'ping'
8
8
 
9
9
  /** Minimal socket-like interface. */
10
10
  interface Socket {