wspromisify 2.6.0 → 2.6.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/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(),r=n.length;let i=r,l=0;for(;i&&l<s;l++)o[l]===e&&(o[l]=n[r-i],i--);for(l=s;i;l++,i--)o[l]=n[r-i];return o},s=(e,o,r)=>{const i=e.length-o.length-t(r);if(i<1)return e(...n(o,r));{const t=(...t)=>s(e,n(o,r),t);return t.$args_left=i,t}},o=e=>(...n)=>e.length>t(n)?s(e,[],n):e(...n);function r(t){return function(n,s){const o=n===e,r=arguments.length;if(1===r&&o)throw new Error("Senseless placeholder usage.");return r>1?o?(t=>function(n){return n===e?t:t(n)})((e=>t(e,s))):t(n,s):e=>t(n,e)}}function i(e){return o(e)}const l=void 0,c=1/0,u=e=>typeof e,a=e=>null===e,h={u:"U",b:"B",n:"N",s:"S",f:"F"},f=Symbol(),d=e=>{const t=u(e);return"object"===t?a(e)?"Null":e.constructor.name:h[t[0]]+t.slice(1)},p=e=>e.length,g=r(((e,t)=>e===t)),m=r(((e,t)=>{const n=d(e);if(g(n,d(t))&&(g(n,"Object")||g(n,"Array"))){if(a(e)||a(t))return g(e,t);if(g(e,t))return!0;for(const n of[e,t])for(const s in n)if(!(g(n,t)&&s in e||g(n,e)&&s in t&&m(e[s],t[s])))return!1;return!0}return g(e,t)})),y=r(((e,t)=>(t.push(e),t))),w=i(((e,t,n)=>n.reduce(e,t))),b=o(((e,t,n,s)=>e(s)?t(s):n(s))),_=(...t)=>(...n)=>{let s,o=!0;for(let r=p(t)-1;r>-1;r--)o?(o=!1,s=t[r](...n)):s=s===e?t[r]():t[r](s);return s},k=r(((e,t)=>t[e])),S=i(((e,t,n)=>n.slice(e,(e=>"number"==u(e))(t)?t:c))),v=k(0);S(1,c);const E=r(((e,t)=>t.find(e))),P=e=>()=>e,W=r(((e,t)=>t.split(e))),j=P(!0),N=P(!1),q=r(((e,t)=>w(((t,n)=>E((t=>e(n,t)),t)?t:y(n,t)),[],t)))(m),z=i(((e,t,n)=>p(t)?(e=>a(e)||(e=>e===l)(e))(n)?e:_((s=>s in n?z(e,S(1,c,t),n[s]):e),v)(t):n));z(l),_(b(m(f),N,j),z(f));const Q=r(((e,t)=>t.map(e))),{floor:A}=Math,C="0123456789abcdefghijklmnopqrstuvwxyz",O=_((e=>Object.fromEntries(e)),Q(((e,t)=>[e,t])),W(""));class ${abc;abclen;c2pos;standard;setABC(e){if(!_(m(p(t=e)),p,q,W(""))(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=O(e)}zip(e){const{abc:t,abclen:n}=this;let s="";for(;e>0;)s=t[e%n]+s,e=A(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 r=0;for(let t=0;t<o;t++)r+=s[e[t]]*n**(o-t-1);return r}constructor(e){this.setABC(e||C+"ABCDEFGHIJKLMNOPQRSTUVWXYZ")}}const B=new $;B.setABC.bind(B),B.zip.bind(B),B.unzip.bind(B);const R=(()=>{try{return WebSocket||null}catch{return null}})(),I=(e,t,n)=>e.addEventListener(t,n),T=(e,t)=>setTimeout(t,e),D={data_type:"json",log:()=>null,timer:!1,url:"localhost",timeout:1400,reconnect:2,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:{}}},U=Symbol("Placeholder"),x=e=>{let t=0;for(const n of e)n!==U&&t++;return t},F=(e,t)=>{const n=e.length,s=e.slice(),o=t.length;let r=o,i=0;for(;r&&i<n;i++)s[i]===U&&(s[i]=t[o-r],r--);for(i=n;r;i++,r--)s[i]=t[o-r];return s},J=(e,t,n)=>{const s=e.length-t.length-x(n);if(s<1)return e(...F(t,n));{const o=(...s)=>J(e,F(t,n),s);return o.$args_left=s,o}},L=e=>(...t)=>e.length>x(t)?J(e,[],t):e(...t);function M(e){return function(t,n){const s=t===U,o=arguments.length;if(1===o&&s)throw new Error("Senseless placeholder usage.");return o>1?s?(e=>function(t){return t===U?e:e(t)})((t=>e(t,n))):e(t,n):n=>e(t,n)}}function G(e){return L(e)}const H=void 0,K=1/0,V=e=>typeof e,X=e=>null===e,Y=e=>"number"==V(e),Z={u:"U",b:"B",n:"N",s:"S",f:"F"},ee=Symbol(),te=e=>{const t=V(e);return"object"===t?X(e)?"Null":e.constructor.name:Z[t[0]]+t.slice(1)},ne=e=>e.length,se=e=>X(e)||(e=>e===H)(e),oe=M(((e,t)=>e===t)),re=M(((e,t)=>{const n=te(e);if(oe(n,te(t))&&(oe(n,"Object")||oe(n,"Array"))){if(X(e)||X(t))return oe(e,t);if(oe(e,t))return!0;for(const n of[e,t])for(const s in n)if(!(oe(n,t)&&s in e||oe(n,e)&&s in t&&re(e[s],t[s])))return!1;return!0}return oe(e,t)})),ie=M(((e,t)=>(t.push(e),t))),le=G(((e,t,n)=>n.reduce(e,t))),ce=L(((e,t,n,s)=>e(s)?t(s):n(s))),ue=(...e)=>(...t)=>{let n,s=!0;for(let o=ne(e)-1;o>-1;o--)s?(s=!1,n=e[o](...t)):n=n===U?e[o]():e[o](n);return n},ae=M(((e,t)=>t[e])),he=G(((e,t,n)=>n.slice(e,Y(t)?t:K))),fe=ae(0);he(1,K);const de=M(((e,t)=>t.find(e))),pe=e=>()=>e,ge=pe(!0),me=pe(!1),ye=M(((e,t)=>le(((t,n)=>de((t=>e(n,t)),t)?t:ie(n,t)),[],t)));ye(re);const we=e=>{let t,n=!1;return(...s)=>n?t:(n=!0,t=e(...s))},be=G(((e,t,n)=>ne(t)?se(n)?e:ue((s=>s in n?be(e,he(1,K,t),n[s]):e),fe)(t):n));be(H),ue(ce(re(ee),me,ge),be(ee));const _e=new $;module.exports=class{open=!1;ws=null;forcibly_closed=!1;reconnect_timeout=null;queue={};messages=[];onReadyQueue=[];onCloseQueue=[];handlers={open:[],close:[],message:[],error:[],timeout:[]};config={};init_flush(){this.queue={},this.messages=[]}call(e,...t){for(const n of this.handlers[e])n(...t)}log(e,t=null,n=null){const s=this.config;null!==n?s.log(e,n,t):s.timer?s.log(e,null,t):s.log(e,t)}initSocket(e){const t=this.config;this.open=!0,this.onReadyQueue.forEach((e=>e())),this.onReadyQueue.splice(0);const{id_key:n,data_key:s}=t.server;if(this.call("open",e),this.messages.forEach((e=>e.send())),null!==this.reconnect_timeout&&(clearInterval(this.reconnect_timeout),this.reconnect_timeout=null),t.ping){const e=setInterval((()=>{this.open&&this.send(t.ping.content),this.forcibly_closed&&clearInterval(e)}),1e3*t.ping.interval)}I(e,"close",(async(...e)=>{this.log("close"),this.open=!1,this.onCloseQueue.forEach((e=>e())),this.onCloseQueue.splice(0),this.call("close",...e);const n=t.reconnect;if("number"!=typeof n||isNaN(n)||this.forcibly_closed)this.ws=null,this.open=!1;else{const e=async()=>{this.log("reconnect"),null!==this.ws&&(this.ws.close(),this.ws=null);null!==await this.connect()&&(this.reconnect_timeout=setTimeout(e,1e3*n))};e()}this.forcibly_closed=!1})),I(e,"message",(e=>{try{const o=t.decode(e.data);if(this.call("message",{...e,data:o}),o[n]){const e=this.queue[o[n]];if(e){const t=e.sent_time?Date.now()-e.sent_time:null;this.log("message",o[s],t),e.ff(o[s]),clearTimeout(e.timeout),delete this.queue[o[n]]}}}catch(t){console.error(t,`WSP: Decode error. Got: ${e.data}`)}}))}connect(){return new Promise((e=>{if(!0===this.open)return e(null);const t=this.config,n=t.socket||t.adapter(t.url,t.protocols);if(this.ws=n,!n||n.readyState>1)return this.ws=null,this.log("error","ready() on closing or closed state! status 2."),e(2);const s=we(e);I(n,"error",we((e=>{this.log("error","status 3."),this.call("error",e),this.ws=null,s(3)}))),n.readyState?(this.initSocket(n),s(null)):I(n,"open",we((()=>{this.log("open"),this.initSocket(n),s(null)})))}))}get socket(){return this.ws}async ready(){return new Promise((e=>{this.open?e():this.onReadyQueue.push(e)}))}on(e,t,n=ge,s=!1){const o=e=>n(e)&&t(e);return s?I(this.ws,e,o):this.handlers[e].push(o)}async close(){return new Promise(((e,t)=>{null===this.ws?t("WSP: closing a non-inited socket!"):(this.open=!1,this.onCloseQueue.push((()=>{this.init_flush(),this.ws=null,this.forcibly_closed=!0,e(null)})),this.ws.close())}))}async send(e,t={}){this.log("send",e);const n=this.config,s={},o=n.server.data_key,r=n.lazy&&!this.open,i=_e.zip(2147483637*Math.random()|0);if("object"==typeof t.top){if(t.top[o])throw new Error("Attempting to set data key/token via send() options!");Object.assign(s,t.top)}if(n.pipes.forEach((t=>e=t(e))),!0===this.open)this.ws.send(n.encode(i,e,n));else if(!1===this.open||r)this.messages.push({send:()=>this.ws.send(n.encode(i,e,n))}),r&&this.connect();else if(null===this.open)throw new Error("Attempting to send via closed WebSocket connection!");return new Promise(((t,s)=>{this.queue[i]={ff:t,data_type:n.data_type,sent_time:n.timer?Date.now():null,timeout:T(n.timeout,(()=>{this.queue[i]&&(this.call("timeout",e),s({"Websocket timeout expired: ":n.timeout,"for the message ":e}),delete this.queue[i])}))}}))}constructor(e={}){this.config=(e=>{if(null===R&&!("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({},D,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.init_flush(),this.config.lazy||this.connect()}};
1
+ "use strict";const t=Symbol("Placeholder"),e=e=>{let n=0;for(const o of e)o!==t&&n++;return n},n=(e,n)=>{const o=e.length,s=e.slice(),r=n.length;let i=r,l=0;for(;i&&l<o;l++)s[l]===t&&(s[l]=n[r-i],i--);for(l=o;i;l++,i--)s[l]=n[r-i];return s},o=(t,s,r)=>{const i=t.length-s.length-e(r);if(i<1)return t(...n(s,r));{const e=(...e)=>o(t,n(s,r),e);return e.$args_left=i,e}},s=t=>(...n)=>t.length>e(n)?o(t,[],n):t(...n);function r(e){return function(n,o){const s=n===t,r=arguments.length;if(1===r&&s)throw new Error("Senseless placeholder usage.");return r>1?s?(e=>function(n){return n===t?e:e(n)})((t=>e(t,o))):e(n,o):t=>e(n,t)}}function i(t){return s(t)}const l=void 0,c=1/0,u=t=>typeof t,a=t=>null===t,h={u:"U",b:"B",n:"N",s:"S",f:"F"},f=Symbol(),d=t=>{const e=u(t);return"object"===e?a(t)?"Null":t.constructor.name:h[e[0]]+e.slice(1)},p=t=>t.length,g=r(((t,e)=>t===e)),m=r(((t,e)=>{const n=d(t);if(g(n,d(e))&&(g(n,"Object")||g(n,"Array"))){if(a(t)||a(e))return g(t,e);if(g(t,e))return!0;for(const n of[t,e])for(const o in n)if(!(g(n,e)&&o in t||g(n,t)&&o in e&&m(t[o],e[o])))return!1;return!0}return g(t,e)})),y=r(((t,e)=>(e.push(t),e))),w=i(((t,e,n)=>n.reduce(t,e))),b=s(((t,e,n,o)=>t(o)?e(o):n(o))),_=(...e)=>(...n)=>{let o,s=!0;for(let r=p(e)-1;r>-1;r--)s?(s=!1,o=e[r](...n)):o=o===t?e[r]():e[r](o);return o},S=r(((t,e)=>e[t])),k=i(((t,e,n)=>n.slice(t,(t=>"number"==u(t))(e)?e:c))),v=S(0);k(1,c);const E=r(((t,e)=>e.find(t))),P=t=>()=>t,W=r(((t,e)=>e.split(t))),j=P(!0),A=P(!1),N=r(((t,e)=>w(((e,n)=>E((e=>t(n,e)),e)?e:y(n,e)),[],e)))(m),q=i(((t,e,n)=>p(e)?(t=>a(t)||(t=>t===l)(t))(n)?t:_((o=>o in n?q(t,k(1,c,e),n[o]):t),v)(e):n));q(l),_(b(m(f),A,j),q(f));const Q=r(((t,e)=>e.map(t))),{floor:z}=Math,C="0123456789abcdefghijklmnopqrstuvwxyz",O=_((t=>Object.fromEntries(t)),Q(((t,e)=>[t,e])),W(""));class ${abc;abclen;c2pos;standard;setABC(t){if(!_(m(p(e=t)),p,N,W(""))(e))throw new Error("Not all chars are unique!");var e;this.abc=t,this.abclen=t.length,this.standard=C.startsWith(t),this.c2pos=O(t)}zip(t){const{abc:e,abclen:n}=this;let o="";for(;t>0;)o=e[t%n]+o,t=z(t/n);return o||"0"}unzip(t){const{standard:e,abclen:n,c2pos:o}=this;if(e)return parseInt(t,n);const s=t.length;let r=0;for(let e=0;e<s;e++)r+=o[t[e]]*n**(s-e-1);return r}constructor(t){this.setABC(t||C+"ABCDEFGHIJKLMNOPQRSTUVWXYZ")}}const B=new $;B.setABC.bind(B),B.zip.bind(B),B.unzip.bind(B);const R=(()=>{try{return WebSocket||null}catch{return null}})(),I=(t,e,n)=>t.addEventListener(e,n),T=(t,e)=>setTimeout(e,t),D={data_type:"json",log:()=>null,timer:!1,url:"localhost",timeout:1400,reconnect:2,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:{}}},U=Symbol("Placeholder"),x=t=>{let e=0;for(const n of t)n!==U&&e++;return e},F=(t,e)=>{const n=t.length,o=t.slice(),s=e.length;let r=s,i=0;for(;r&&i<n;i++)o[i]===U&&(o[i]=e[s-r],r--);for(i=n;r;i++,r--)o[i]=e[s-r];return o},J=(t,e,n)=>{const o=t.length-e.length-x(n);if(o<1)return t(...F(e,n));{const s=(...o)=>J(t,F(e,n),o);return s.$args_left=o,s}},L=t=>(...e)=>t.length>x(e)?J(t,[],e):t(...e);function M(t){return function(e,n){const o=e===U,s=arguments.length;if(1===s&&o)throw new Error("Senseless placeholder usage.");return s>1?o?(t=>function(e){return e===U?t:t(e)})((e=>t(e,n))):t(e,n):n=>t(e,n)}}function G(t){return L(t)}const H=void 0,K=1/0,V=t=>typeof t,X=t=>null===t,Y=t=>"number"==V(t),Z={u:"U",b:"B",n:"N",s:"S",f:"F"},tt=Symbol(),et=t=>{const e=V(t);return"object"===e?X(t)?"Null":t.constructor.name:Z[e[0]]+e.slice(1)},nt=t=>t.length,ot=t=>X(t)||(t=>t===H)(t),st=M(((t,e)=>t===e)),rt=M(((t,e)=>{const n=et(t);if(st(n,et(e))&&(st(n,"Object")||st(n,"Array"))){if(X(t)||X(e))return st(t,e);if(st(t,e))return!0;for(const n of[t,e])for(const o in n)if(!(st(n,e)&&o in t||st(n,t)&&o in e&&rt(t[o],e[o])))return!1;return!0}return st(t,e)})),it=M(((t,e)=>(e.push(t),e))),lt=G(((t,e,n)=>n.reduce(t,e))),ct=M(((t,e)=>{const n=(t=>Array.isArray(t))(e);let o,s;n&&(o=0,s=[]);for(let o in e)t(e[o],o)||(n?s.push(+o):delete e[o]);if(n)for(const t of s)e.splice(t-o++,1);return e})),ut=L(((t,e,n,o)=>t(o)?e(o):n(o))),at=(...t)=>(...e)=>{let n,o=!0;for(let s=nt(t)-1;s>-1;s--)o?(o=!1,n=t[s](...e)):n=n===U?t[s]():t[s](n);return n},ht=M(((t,e)=>e[t])),ft=G(((t,e,n)=>n.slice(t,Y(e)?e:K))),dt=ht(0);ft(1,K);const pt=M(((t,e)=>e.find(t))),gt=t=>()=>t,mt=gt(!0),yt=gt(!1),wt=M(((t,e)=>lt(((e,n)=>pt((e=>t(n,e)),e)?e:it(n,e)),[],e)));wt(rt);const bt=t=>{let e,n=!1;return(...o)=>n?e:(n=!0,e=t(...o))},_t=G(((t,e,n)=>nt(e)?ot(n)?t:at((o=>o in n?_t(t,ft(1,K,e),n[o]):t),dt)(e):n));_t(H),at(ut(rt(tt),yt,mt),_t(tt));const St=new $;module.exports=class{open=!1;ws=null;forcibly_closed=!1;reconnect_timeout=null;queue={};onReadyQueue=[];onCloseQueue=[];handlers={open:[],close:[],message:[],error:[],timeout:[]};config={};init_flush(){ct(yt,this.queue)}call(t,...e){for(const n of this.handlers[t])n(...e)}log(t,e=null,n=null){const o=this.config;null!==n?o.log(t,n,e):o.timer?o.log(t,null,e):o.log(t,e)}initSocket(t){const{queue:e,config:n}=this;this.open=!0,this.onReadyQueue.forEach((t=>t())),this.onReadyQueue.splice(0);const{id_key:o,data_key:s}=n.server;this.call("open",t);for(const n in e)t.send(e[n].msg);if(null!==this.reconnect_timeout&&(clearInterval(this.reconnect_timeout),this.reconnect_timeout=null),n.ping){const t=setInterval((()=>{this.open&&this.send(n.ping.content),this.forcibly_closed&&clearInterval(t)}),1e3*n.ping.interval)}I(t,"close",(async(...t)=>{this.log("close"),this.open=!1,this.ws=null,this.onCloseQueue.forEach((t=>t())),this.onCloseQueue.splice(0),this.call("close",...t);const e=n.reconnect;if("number"==typeof e&&!isNaN(e)&&!this.forcibly_closed){const t=async()=>{this.log("reconnect"),null!==this.ws&&(this.ws.close(),this.ws=null);null!==await this.connect()&&(this.reconnect_timeout=setTimeout(t,1e3*e))};t()}this.forcibly_closed=!1})),I(t,"message",(t=>{try{const e=n.decode(t.data);if(this.call("message",{...t,data:e}),e[o]){const t=this.queue[e[o]];if(t){const n=t.sent_time?Date.now()-t.sent_time:null;this.log("message",e[s],n),t.ff(e[s])}}}catch(e){console.error(e,`WSP: Decode error. Got: ${t.data}`)}}))}connect(){return new Promise((t=>{if(!0===this.open)return t(null);const e=this.config,n=e.socket||e.adapter(e.url,e.protocols);if(this.ws=n,!n||n.readyState>1)return this.ws=null,this.log("error","ready() on closing or closed state! status 2."),t(2);const o=bt(t);I(n,"error",bt((t=>{this.log("error","status 3. Err: "+t.message),this.call("error",t),this.ws=null,o(3)}))),n.readyState?(this.initSocket(n),o(null)):I(n,"open",bt((()=>{this.log("open"),this.initSocket(n),o(null)})))}))}get socket(){return this.ws}async ready(){return new Promise((t=>{this.open?t():this.onReadyQueue.push(t)}))}on(t,e,n=mt,o=!1){const s=t=>n(t)&&e(t);return o?I(this.ws,t,s):this.handlers[t].push(s)}async close(){return new Promise(((t,e)=>{null===this.ws?e("WSP: closing a non-inited socket!"):(this.open=!1,this.onCloseQueue.push((()=>{this.init_flush(),this.ws=null,this.forcibly_closed=!0,t(null)})),this.ws.close())}))}async send(t,e={}){this.log("send",t);const{config:n,ws:o,forcibly_closed:s,queue:r}=this,i={},l=n.server.data_key,c=St.zip(2147483637*Math.random()|0);if("object"==typeof e.top){if(e.top[l])throw new Error("Attempting to set data key/token via send() options!");Object.assign(i,e.top)}if(n.pipes.forEach((e=>t=e(t))),s)throw new Error("Attempting to send via closed WebSocket connection!");this.open||this.connect();const u=await n.encode(c,t,n);return 1===o?.readyState&&o.send(u),new Promise(((e,o)=>{this.queue[c]={msg:u,ff(t){e(t),clearTimeout(this.timeout),delete r[c]},data_type:n.data_type,sent_time:n.timer?Date.now():null,timeout:T(n.timeout,(()=>{this.queue[c]&&(this.call("timeout",t),o({"Websocket timeout expired: ":n.timeout,"for the message ":t}),delete r[c])}))}}))}constructor(t={}){this.config=(t=>{if(null===R&&!("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({},D,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.init_flush(),this.config.lazy||this.connect()}};
package/dist/bundle.d.ts CHANGED
@@ -47,6 +47,13 @@ declare namespace wsc {
47
47
  top: any;
48
48
  data_type: DataType;
49
49
  }
50
+ interface Message {
51
+ msg: any;
52
+ ff(x: any): any;
53
+ data_type: DataType;
54
+ sent_time: number | null;
55
+ timeout: NodeJS.Timeout;
56
+ }
50
57
  }
51
58
  declare class WebSocketClient {
52
59
  private open;
@@ -54,7 +61,6 @@ declare class WebSocketClient {
54
61
  private forcibly_closed;
55
62
  private reconnect_timeout;
56
63
  private queue;
57
- private messages;
58
64
  private onReadyQueue;
59
65
  private onCloseQueue;
60
66
  private handlers;
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(),r=n.length;let i=r,l=0;for(;i&&l<s;l++)o[l]===e&&(o[l]=n[r-i],i--);for(l=s;i;l++,i--)o[l]=n[r-i];return o},s=(e,o,r)=>{const i=e.length-o.length-t(r);if(i<1)return e(...n(o,r));{const t=(...t)=>s(e,n(o,r),t);return t.$args_left=i,t}},o=e=>(...n)=>e.length>t(n)?s(e,[],n):e(...n);function r(t){return function(n,s){const o=n===e,r=arguments.length;if(1===r&&o)throw new Error("Senseless placeholder usage.");return r>1?o?(t=>function(n){return n===e?t:t(n)})((e=>t(e,s))):t(n,s):e=>t(n,e)}}function i(e){return o(e)}const l=void 0,c=1/0,u=e=>typeof e,a=e=>null===e,h={u:"U",b:"B",n:"N",s:"S",f:"F"},f=Symbol(),d=e=>{const t=u(e);return"object"===t?a(e)?"Null":e.constructor.name:h[t[0]]+t.slice(1)},p=e=>e.length,g=r(((e,t)=>e===t)),m=r(((e,t)=>{const n=d(e);if(g(n,d(t))&&(g(n,"Object")||g(n,"Array"))){if(a(e)||a(t))return g(e,t);if(g(e,t))return!0;for(const n of[e,t])for(const s in n)if(!(g(n,t)&&s in e||g(n,e)&&s in t&&m(e[s],t[s])))return!1;return!0}return g(e,t)})),y=r(((e,t)=>(t.push(e),t))),w=i(((e,t,n)=>n.reduce(e,t))),b=o(((e,t,n,s)=>e(s)?t(s):n(s))),_=(...t)=>(...n)=>{let s,o=!0;for(let r=p(t)-1;r>-1;r--)o?(o=!1,s=t[r](...n)):s=s===e?t[r]():t[r](s);return s},k=r(((e,t)=>t[e])),S=i(((e,t,n)=>n.slice(e,(e=>"number"==u(e))(t)?t:c))),v=k(0);S(1,c);const E=r(((e,t)=>t.find(e))),P=e=>()=>e,W=r(((e,t)=>t.split(e))),j=P(!0),N=P(!1),q=r(((e,t)=>w(((t,n)=>E((t=>e(n,t)),t)?t:y(n,t)),[],t)))(m),z=i(((e,t,n)=>p(t)?(e=>a(e)||(e=>e===l)(e))(n)?e:_((s=>s in n?z(e,S(1,c,t),n[s]):e),v)(t):n));z(l),_(b(m(f),N,j),z(f));const Q=r(((e,t)=>t.map(e))),{floor:A}=Math,C="0123456789abcdefghijklmnopqrstuvwxyz",O=_((e=>Object.fromEntries(e)),Q(((e,t)=>[e,t])),W(""));class ${abc;abclen;c2pos;standard;setABC(e){if(!_(m(p(t=e)),p,q,W(""))(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=O(e)}zip(e){const{abc:t,abclen:n}=this;let s="";for(;e>0;)s=t[e%n]+s,e=A(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 r=0;for(let t=0;t<o;t++)r+=s[e[t]]*n**(o-t-1);return r}constructor(e){this.setABC(e||C+"ABCDEFGHIJKLMNOPQRSTUVWXYZ")}}const B=new $;B.setABC.bind(B),B.zip.bind(B),B.unzip.bind(B);const R=(()=>{try{return WebSocket||null}catch{return null}})(),I=(e,t,n)=>e.addEventListener(t,n),T=(e,t)=>setTimeout(t,e),D={data_type:"json",log:()=>null,timer:!1,url:"localhost",timeout:1400,reconnect:2,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:{}}},U=Symbol("Placeholder"),x=e=>{let t=0;for(const n of e)n!==U&&t++;return t},F=(e,t)=>{const n=e.length,s=e.slice(),o=t.length;let r=o,i=0;for(;r&&i<n;i++)s[i]===U&&(s[i]=t[o-r],r--);for(i=n;r;i++,r--)s[i]=t[o-r];return s},J=(e,t,n)=>{const s=e.length-t.length-x(n);if(s<1)return e(...F(t,n));{const o=(...s)=>J(e,F(t,n),s);return o.$args_left=s,o}},L=e=>(...t)=>e.length>x(t)?J(e,[],t):e(...t);function M(e){return function(t,n){const s=t===U,o=arguments.length;if(1===o&&s)throw new Error("Senseless placeholder usage.");return o>1?s?(e=>function(t){return t===U?e:e(t)})((t=>e(t,n))):e(t,n):n=>e(t,n)}}function G(e){return L(e)}const H=void 0,K=1/0,V=e=>typeof e,X=e=>null===e,Y=e=>"number"==V(e),Z={u:"U",b:"B",n:"N",s:"S",f:"F"},ee=Symbol(),te=e=>{const t=V(e);return"object"===t?X(e)?"Null":e.constructor.name:Z[t[0]]+t.slice(1)},ne=e=>e.length,se=e=>X(e)||(e=>e===H)(e),oe=M(((e,t)=>e===t)),re=M(((e,t)=>{const n=te(e);if(oe(n,te(t))&&(oe(n,"Object")||oe(n,"Array"))){if(X(e)||X(t))return oe(e,t);if(oe(e,t))return!0;for(const n of[e,t])for(const s in n)if(!(oe(n,t)&&s in e||oe(n,e)&&s in t&&re(e[s],t[s])))return!1;return!0}return oe(e,t)})),ie=M(((e,t)=>(t.push(e),t))),le=G(((e,t,n)=>n.reduce(e,t))),ce=L(((e,t,n,s)=>e(s)?t(s):n(s))),ue=(...e)=>(...t)=>{let n,s=!0;for(let o=ne(e)-1;o>-1;o--)s?(s=!1,n=e[o](...t)):n=n===U?e[o]():e[o](n);return n},ae=M(((e,t)=>t[e])),he=G(((e,t,n)=>n.slice(e,Y(t)?t:K))),fe=ae(0);he(1,K);const de=M(((e,t)=>t.find(e))),pe=e=>()=>e,ge=pe(!0),me=pe(!1),ye=M(((e,t)=>le(((t,n)=>de((t=>e(n,t)),t)?t:ie(n,t)),[],t)));ye(re);const we=e=>{let t,n=!1;return(...s)=>n?t:(n=!0,t=e(...s))},be=G(((e,t,n)=>ne(t)?se(n)?e:ue((s=>s in n?be(e,he(1,K,t),n[s]):e),fe)(t):n));be(H),ue(ce(re(ee),me,ge),be(ee));const _e=new $;class ke{open=!1;ws=null;forcibly_closed=!1;reconnect_timeout=null;queue={};messages=[];onReadyQueue=[];onCloseQueue=[];handlers={open:[],close:[],message:[],error:[],timeout:[]};config={};init_flush(){this.queue={},this.messages=[]}call(e,...t){for(const n of this.handlers[e])n(...t)}log(e,t=null,n=null){const s=this.config;null!==n?s.log(e,n,t):s.timer?s.log(e,null,t):s.log(e,t)}initSocket(e){const t=this.config;this.open=!0,this.onReadyQueue.forEach((e=>e())),this.onReadyQueue.splice(0);const{id_key:n,data_key:s}=t.server;if(this.call("open",e),this.messages.forEach((e=>e.send())),null!==this.reconnect_timeout&&(clearInterval(this.reconnect_timeout),this.reconnect_timeout=null),t.ping){const e=setInterval((()=>{this.open&&this.send(t.ping.content),this.forcibly_closed&&clearInterval(e)}),1e3*t.ping.interval)}I(e,"close",(async(...e)=>{this.log("close"),this.open=!1,this.onCloseQueue.forEach((e=>e())),this.onCloseQueue.splice(0),this.call("close",...e);const n=t.reconnect;if("number"!=typeof n||isNaN(n)||this.forcibly_closed)this.ws=null,this.open=!1;else{const e=async()=>{this.log("reconnect"),null!==this.ws&&(this.ws.close(),this.ws=null);null!==await this.connect()&&(this.reconnect_timeout=setTimeout(e,1e3*n))};e()}this.forcibly_closed=!1})),I(e,"message",(e=>{try{const o=t.decode(e.data);if(this.call("message",{...e,data:o}),o[n]){const e=this.queue[o[n]];if(e){const t=e.sent_time?Date.now()-e.sent_time:null;this.log("message",o[s],t),e.ff(o[s]),clearTimeout(e.timeout),delete this.queue[o[n]]}}}catch(t){console.error(t,`WSP: Decode error. Got: ${e.data}`)}}))}connect(){return new Promise((e=>{if(!0===this.open)return e(null);const t=this.config,n=t.socket||t.adapter(t.url,t.protocols);if(this.ws=n,!n||n.readyState>1)return this.ws=null,this.log("error","ready() on closing or closed state! status 2."),e(2);const s=we(e);I(n,"error",we((e=>{this.log("error","status 3."),this.call("error",e),this.ws=null,s(3)}))),n.readyState?(this.initSocket(n),s(null)):I(n,"open",we((()=>{this.log("open"),this.initSocket(n),s(null)})))}))}get socket(){return this.ws}async ready(){return new Promise((e=>{this.open?e():this.onReadyQueue.push(e)}))}on(e,t,n=ge,s=!1){const o=e=>n(e)&&t(e);return s?I(this.ws,e,o):this.handlers[e].push(o)}async close(){return new Promise(((e,t)=>{null===this.ws?t("WSP: closing a non-inited socket!"):(this.open=!1,this.onCloseQueue.push((()=>{this.init_flush(),this.ws=null,this.forcibly_closed=!0,e(null)})),this.ws.close())}))}async send(e,t={}){this.log("send",e);const n=this.config,s={},o=n.server.data_key,r=n.lazy&&!this.open,i=_e.zip(2147483637*Math.random()|0);if("object"==typeof t.top){if(t.top[o])throw new Error("Attempting to set data key/token via send() options!");Object.assign(s,t.top)}if(n.pipes.forEach((t=>e=t(e))),!0===this.open)this.ws.send(n.encode(i,e,n));else if(!1===this.open||r)this.messages.push({send:()=>this.ws.send(n.encode(i,e,n))}),r&&this.connect();else if(null===this.open)throw new Error("Attempting to send via closed WebSocket connection!");return new Promise(((t,s)=>{this.queue[i]={ff:t,data_type:n.data_type,sent_time:n.timer?Date.now():null,timeout:T(n.timeout,(()=>{this.queue[i]&&(this.call("timeout",e),s({"Websocket timeout expired: ":n.timeout,"for the message ":e}),delete this.queue[i])}))}}))}constructor(e={}){this.config=(e=>{if(null===R&&!("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({},D,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.init_flush(),this.config.lazy||this.connect()}}export{ke as default};
1
+ const t=Symbol("Placeholder"),e=e=>{let n=0;for(const o of e)o!==t&&n++;return n},n=(e,n)=>{const o=e.length,s=e.slice(),r=n.length;let i=r,l=0;for(;i&&l<o;l++)s[l]===t&&(s[l]=n[r-i],i--);for(l=o;i;l++,i--)s[l]=n[r-i];return s},o=(t,s,r)=>{const i=t.length-s.length-e(r);if(i<1)return t(...n(s,r));{const e=(...e)=>o(t,n(s,r),e);return e.$args_left=i,e}},s=t=>(...n)=>t.length>e(n)?o(t,[],n):t(...n);function r(e){return function(n,o){const s=n===t,r=arguments.length;if(1===r&&s)throw new Error("Senseless placeholder usage.");return r>1?s?(e=>function(n){return n===t?e:e(n)})((t=>e(t,o))):e(n,o):t=>e(n,t)}}function i(t){return s(t)}const l=void 0,c=1/0,u=t=>typeof t,a=t=>null===t,h={u:"U",b:"B",n:"N",s:"S",f:"F"},f=Symbol(),d=t=>{const e=u(t);return"object"===e?a(t)?"Null":t.constructor.name:h[e[0]]+e.slice(1)},p=t=>t.length,g=r(((t,e)=>t===e)),m=r(((t,e)=>{const n=d(t);if(g(n,d(e))&&(g(n,"Object")||g(n,"Array"))){if(a(t)||a(e))return g(t,e);if(g(t,e))return!0;for(const n of[t,e])for(const o in n)if(!(g(n,e)&&o in t||g(n,t)&&o in e&&m(t[o],e[o])))return!1;return!0}return g(t,e)})),y=r(((t,e)=>(e.push(t),e))),w=i(((t,e,n)=>n.reduce(t,e))),b=s(((t,e,n,o)=>t(o)?e(o):n(o))),_=(...e)=>(...n)=>{let o,s=!0;for(let r=p(e)-1;r>-1;r--)s?(s=!1,o=e[r](...n)):o=o===t?e[r]():e[r](o);return o},S=r(((t,e)=>e[t])),k=i(((t,e,n)=>n.slice(t,(t=>"number"==u(t))(e)?e:c))),v=S(0);k(1,c);const E=r(((t,e)=>e.find(t))),P=t=>()=>t,W=r(((t,e)=>e.split(t))),j=P(!0),A=P(!1),N=r(((t,e)=>w(((e,n)=>E((e=>t(n,e)),e)?e:y(n,e)),[],e)))(m),q=i(((t,e,n)=>p(e)?(t=>a(t)||(t=>t===l)(t))(n)?t:_((o=>o in n?q(t,k(1,c,e),n[o]):t),v)(e):n));q(l),_(b(m(f),A,j),q(f));const Q=r(((t,e)=>e.map(t))),{floor:z}=Math,C="0123456789abcdefghijklmnopqrstuvwxyz",O=_((t=>Object.fromEntries(t)),Q(((t,e)=>[t,e])),W(""));class ${abc;abclen;c2pos;standard;setABC(t){if(!_(m(p(e=t)),p,N,W(""))(e))throw new Error("Not all chars are unique!");var e;this.abc=t,this.abclen=t.length,this.standard=C.startsWith(t),this.c2pos=O(t)}zip(t){const{abc:e,abclen:n}=this;let o="";for(;t>0;)o=e[t%n]+o,t=z(t/n);return o||"0"}unzip(t){const{standard:e,abclen:n,c2pos:o}=this;if(e)return parseInt(t,n);const s=t.length;let r=0;for(let e=0;e<s;e++)r+=o[t[e]]*n**(s-e-1);return r}constructor(t){this.setABC(t||C+"ABCDEFGHIJKLMNOPQRSTUVWXYZ")}}const B=new $;B.setABC.bind(B),B.zip.bind(B),B.unzip.bind(B);const R=(()=>{try{return WebSocket||null}catch{return null}})(),I=(t,e,n)=>t.addEventListener(e,n),T=(t,e)=>setTimeout(e,t),D={data_type:"json",log:()=>null,timer:!1,url:"localhost",timeout:1400,reconnect:2,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:{}}},U=Symbol("Placeholder"),x=t=>{let e=0;for(const n of t)n!==U&&e++;return e},F=(t,e)=>{const n=t.length,o=t.slice(),s=e.length;let r=s,i=0;for(;r&&i<n;i++)o[i]===U&&(o[i]=e[s-r],r--);for(i=n;r;i++,r--)o[i]=e[s-r];return o},J=(t,e,n)=>{const o=t.length-e.length-x(n);if(o<1)return t(...F(e,n));{const s=(...o)=>J(t,F(e,n),o);return s.$args_left=o,s}},L=t=>(...e)=>t.length>x(e)?J(t,[],e):t(...e);function M(t){return function(e,n){const o=e===U,s=arguments.length;if(1===s&&o)throw new Error("Senseless placeholder usage.");return s>1?o?(t=>function(e){return e===U?t:t(e)})((e=>t(e,n))):t(e,n):n=>t(e,n)}}function G(t){return L(t)}const H=void 0,K=1/0,V=t=>typeof t,X=t=>null===t,Y=t=>"number"==V(t),Z={u:"U",b:"B",n:"N",s:"S",f:"F"},tt=Symbol(),et=t=>{const e=V(t);return"object"===e?X(t)?"Null":t.constructor.name:Z[e[0]]+e.slice(1)},nt=t=>t.length,ot=t=>X(t)||(t=>t===H)(t),st=M(((t,e)=>t===e)),rt=M(((t,e)=>{const n=et(t);if(st(n,et(e))&&(st(n,"Object")||st(n,"Array"))){if(X(t)||X(e))return st(t,e);if(st(t,e))return!0;for(const n of[t,e])for(const o in n)if(!(st(n,e)&&o in t||st(n,t)&&o in e&&rt(t[o],e[o])))return!1;return!0}return st(t,e)})),it=M(((t,e)=>(e.push(t),e))),lt=G(((t,e,n)=>n.reduce(t,e))),ct=M(((t,e)=>{const n=(t=>Array.isArray(t))(e);let o,s;n&&(o=0,s=[]);for(let o in e)t(e[o],o)||(n?s.push(+o):delete e[o]);if(n)for(const t of s)e.splice(t-o++,1);return e})),ut=L(((t,e,n,o)=>t(o)?e(o):n(o))),at=(...t)=>(...e)=>{let n,o=!0;for(let s=nt(t)-1;s>-1;s--)o?(o=!1,n=t[s](...e)):n=n===U?t[s]():t[s](n);return n},ht=M(((t,e)=>e[t])),ft=G(((t,e,n)=>n.slice(t,Y(e)?e:K))),dt=ht(0);ft(1,K);const pt=M(((t,e)=>e.find(t))),gt=t=>()=>t,mt=gt(!0),yt=gt(!1),wt=M(((t,e)=>lt(((e,n)=>pt((e=>t(n,e)),e)?e:it(n,e)),[],e)));wt(rt);const bt=t=>{let e,n=!1;return(...o)=>n?e:(n=!0,e=t(...o))},_t=G(((t,e,n)=>nt(e)?ot(n)?t:at((o=>o in n?_t(t,ft(1,K,e),n[o]):t),dt)(e):n));_t(H),at(ut(rt(tt),yt,mt),_t(tt));const St=new $;class kt{open=!1;ws=null;forcibly_closed=!1;reconnect_timeout=null;queue={};onReadyQueue=[];onCloseQueue=[];handlers={open:[],close:[],message:[],error:[],timeout:[]};config={};init_flush(){ct(yt,this.queue)}call(t,...e){for(const n of this.handlers[t])n(...e)}log(t,e=null,n=null){const o=this.config;null!==n?o.log(t,n,e):o.timer?o.log(t,null,e):o.log(t,e)}initSocket(t){const{queue:e,config:n}=this;this.open=!0,this.onReadyQueue.forEach((t=>t())),this.onReadyQueue.splice(0);const{id_key:o,data_key:s}=n.server;this.call("open",t);for(const n in e)t.send(e[n].msg);if(null!==this.reconnect_timeout&&(clearInterval(this.reconnect_timeout),this.reconnect_timeout=null),n.ping){const t=setInterval((()=>{this.open&&this.send(n.ping.content),this.forcibly_closed&&clearInterval(t)}),1e3*n.ping.interval)}I(t,"close",(async(...t)=>{this.log("close"),this.open=!1,this.ws=null,this.onCloseQueue.forEach((t=>t())),this.onCloseQueue.splice(0),this.call("close",...t);const e=n.reconnect;if("number"==typeof e&&!isNaN(e)&&!this.forcibly_closed){const t=async()=>{this.log("reconnect"),null!==this.ws&&(this.ws.close(),this.ws=null);null!==await this.connect()&&(this.reconnect_timeout=setTimeout(t,1e3*e))};t()}this.forcibly_closed=!1})),I(t,"message",(t=>{try{const e=n.decode(t.data);if(this.call("message",{...t,data:e}),e[o]){const t=this.queue[e[o]];if(t){const n=t.sent_time?Date.now()-t.sent_time:null;this.log("message",e[s],n),t.ff(e[s])}}}catch(e){console.error(e,`WSP: Decode error. Got: ${t.data}`)}}))}connect(){return new Promise((t=>{if(!0===this.open)return t(null);const e=this.config,n=e.socket||e.adapter(e.url,e.protocols);if(this.ws=n,!n||n.readyState>1)return this.ws=null,this.log("error","ready() on closing or closed state! status 2."),t(2);const o=bt(t);I(n,"error",bt((t=>{this.log("error","status 3. Err: "+t.message),this.call("error",t),this.ws=null,o(3)}))),n.readyState?(this.initSocket(n),o(null)):I(n,"open",bt((()=>{this.log("open"),this.initSocket(n),o(null)})))}))}get socket(){return this.ws}async ready(){return new Promise((t=>{this.open?t():this.onReadyQueue.push(t)}))}on(t,e,n=mt,o=!1){const s=t=>n(t)&&e(t);return o?I(this.ws,t,s):this.handlers[t].push(s)}async close(){return new Promise(((t,e)=>{null===this.ws?e("WSP: closing a non-inited socket!"):(this.open=!1,this.onCloseQueue.push((()=>{this.init_flush(),this.ws=null,this.forcibly_closed=!0,t(null)})),this.ws.close())}))}async send(t,e={}){this.log("send",t);const{config:n,ws:o,forcibly_closed:s,queue:r}=this,i={},l=n.server.data_key,c=St.zip(2147483637*Math.random()|0);if("object"==typeof e.top){if(e.top[l])throw new Error("Attempting to set data key/token via send() options!");Object.assign(i,e.top)}if(n.pipes.forEach((e=>t=e(t))),s)throw new Error("Attempting to send via closed WebSocket connection!");this.open||this.connect();const u=await n.encode(c,t,n);return 1===o?.readyState&&o.send(u),new Promise(((e,o)=>{this.queue[c]={msg:u,ff(t){e(t),clearTimeout(this.timeout),delete r[c]},data_type:n.data_type,sent_time:n.timer?Date.now():null,timeout:T(n.timeout,(()=>{this.queue[c]&&(this.call("timeout",t),o({"Websocket timeout expired: ":n.timeout,"for the message ":t}),delete r[c])}))}}))}constructor(t={}){this.config=(t=>{if(null===R&&!("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({},D,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.init_flush(),this.config.lazy||this.connect()}}export{kt 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.6.0",
44
+ "version": "2.6.2",
45
45
  "type": "module",
46
46
  "exports": {
47
47
  ".": {
@@ -53,27 +53,27 @@
53
53
  },
54
54
  "devDependencies": {
55
55
  "@rollup/plugin-commonjs": "^28.0.3",
56
- "@rollup/plugin-node-resolve": "^16.0.0",
56
+ "@rollup/plugin-node-resolve": "^16.0.1",
57
57
  "@rollup/plugin-replace": "^6.0.2",
58
58
  "@rollup/plugin-terser": "^0.4.4",
59
- "@types/express": "^5.0.0",
60
- "@types/node": "^22.13.9",
61
- "@types/ws": "^8.18.0",
59
+ "@types/express": "^5.0.1",
60
+ "@types/node": "^22.15.2",
61
+ "@types/ws": "^8.18.1",
62
62
  "codecov": "^3.8.3",
63
63
  "cross-env": "^7.0.3",
64
64
  "dts-bundle-generator": "^9.5.1",
65
65
  "nyc": "^17.1.0",
66
- "pepka": "^1.6.2",
67
- "rollup": "^4.34.9",
66
+ "rollup": "^4.40.0",
68
67
  "rollup-plugin-typescript2": "^0.36.0",
69
68
  "ts-node": "^10.9.2",
70
69
  "tsx": "^4.19.3",
71
- "typescript": "^5.8.2",
70
+ "typescript": "^5.8.3",
72
71
  "uvu": "^0.5.6",
73
72
  "ws": "^8.18.1"
74
73
  },
75
74
  "types": "./dist/bundle.d.ts",
76
75
  "dependencies": {
76
+ "pepka": "^1.6.3",
77
77
  "zipnum": "^2.0.0"
78
78
  }
79
79
  }
package/src/WSC.ts CHANGED
@@ -2,7 +2,7 @@ import './types'
2
2
  import { Zipnum } from 'zipnum'
3
3
  import { add_event, sett } from './utils'
4
4
  import { processConfig } from './config'
5
- import { AnyFunc, once, T } from 'pepka'
5
+ import { AnyFunc, F, once, qfilter, T } from 'pepka'
6
6
 
7
7
  const MAX_32 = 2**31 - 1
8
8
  const zipnum = new Zipnum()
@@ -21,16 +21,15 @@ class WebSocketClient {
21
21
  private ws: wsc.Socket|null = null
22
22
  private forcibly_closed = false
23
23
  private reconnect_timeout: NodeJS.Timeout|null = null
24
- private queue = {}
25
- private messages: any[] = []
24
+ private queue: Record<string, wsc.Message> = {}
26
25
  private onReadyQueue: AnyFunc[] = []
27
26
  private onCloseQueue: AnyFunc[] = []
28
27
  private handlers: EventHandlers = { open: [], close: [], message: [], error: [], timeout: [] }
29
28
  private config = <wsc.Config>{}
30
29
 
31
30
  private init_flush(): void {
32
- this.queue = {} // data queuse
33
- this.messages = [] // send() queue
31
+ // TODO: reject them or save somehow ?..
32
+ qfilter(F, this.queue)
34
33
  }
35
34
  private call(event_name: wsc.WSEvent, ...args: any[]) {
36
35
  // this.handlers.open[0]()
@@ -51,16 +50,14 @@ class WebSocketClient {
51
50
  }
52
51
 
53
52
  private initSocket(ws: wsc.Socket) {
54
- const config = this.config
53
+ const {queue, config} = this
55
54
  this.open = true
56
55
  this.onReadyQueue.forEach((fn: Function) => fn())
57
56
  this.onReadyQueue.splice(0)
58
57
  const {id_key, data_key} = config.server
59
58
  // Works also on previously opened sockets that do not fire 'open' event.
60
59
  this.call('open', ws)
61
- // Send all pending messages.
62
- this.messages.forEach((message: any) => message.send())
63
- // It's reconnecting.
60
+ for(const msg_id in queue) ws.send(queue[msg_id].msg)
64
61
  if(this.reconnect_timeout !== null) {
65
62
  clearInterval(this.reconnect_timeout)
66
63
  this.reconnect_timeout = null
@@ -74,6 +71,7 @@ class WebSocketClient {
74
71
  add_event(ws, 'close', async (...e) => {
75
72
  this.log('close')
76
73
  this.open = false
74
+ this.ws = null
77
75
  this.onCloseQueue.forEach((fn: Function) => fn())
78
76
  this.onCloseQueue.splice(0)
79
77
  this.call('close', ...e)
@@ -97,9 +95,6 @@ class WebSocketClient {
97
95
  }
98
96
  // TODO: test normal close by server. Would it be infinite ?
99
97
  reconnectFunc()
100
- } else {
101
- this.ws = null
102
- this.open = false
103
98
  }
104
99
  // reset the flag to reuse.
105
100
  this.forcibly_closed = false
@@ -116,8 +111,6 @@ class WebSocketClient {
116
111
  this.log('message', data[data_key], time)
117
112
  // Play.
118
113
  q.ff(data[data_key])
119
- clearTimeout(q.timeout)
120
- delete this.queue[data[id_key]]
121
114
  }
122
115
  }
123
116
  } catch (err) {
@@ -141,7 +134,7 @@ class WebSocketClient {
141
134
  }
142
135
  const ffo = once(ff)
143
136
  add_event(ws, 'error', once((e) => {
144
- this.log('error', 'status 3.')
137
+ this.log('error', 'status 3. Err: '+e.message)
145
138
  this.call('error', e)
146
139
  this.ws = null
147
140
  // Some network error: Connection refused or so.
@@ -163,11 +156,8 @@ class WebSocketClient {
163
156
  public get socket() { return this.ws }
164
157
  public async ready() {
165
158
  return new Promise<void>((ff) => {
166
- if(this.open) {
167
- ff()
168
- } else {
169
- this.onReadyQueue.push(ff)
170
- }
159
+ if(this.open) ff()
160
+ else this.onReadyQueue.push(ff)
171
161
  })
172
162
  }
173
163
  public on(
@@ -209,10 +199,9 @@ class WebSocketClient {
209
199
  opts = <wsc.SendOptions>{}
210
200
  ): Promise<ResponseDataType> {
211
201
  this.log('send', message_data)
212
- const config = this.config
202
+ const {config, ws, forcibly_closed, queue} = this
213
203
  const message = {}
214
204
  const data_key = config.server.data_key
215
- const first_time_lazy = config.lazy && !this.open
216
205
 
217
206
  const message_id = zipnum.zip((Math.random()*(MAX_32-10))|0)
218
207
  if(typeof opts.top === 'object') {
@@ -223,21 +212,21 @@ class WebSocketClient {
223
212
  }
224
213
  config.pipes.forEach((pipe) => message_data = pipe(message_data))
225
214
 
226
- if(this.open === true) {
227
- (this.ws as wsc.Socket).send(config.encode(message_id, message_data, config))
228
- } else if(this.open === false || first_time_lazy) {
229
- this.messages.push({
230
- send: () => (this.ws as wsc.Socket).send(config.encode(message_id, message_data, config))
231
- })
232
- if(first_time_lazy) this.connect()
233
- } else if(this.open === null) {
215
+ if(forcibly_closed)
234
216
  throw new Error('Attempting to send via closed WebSocket connection!')
235
- }
217
+ if(!this.open) this.connect()
218
+ const msg = await config.encode(message_id, message_data, config)
219
+ if(ws?.readyState===1) // The only opened state.
220
+ ws.send(msg)
236
221
 
237
222
  return new Promise((ff, rj) => {
238
- // TODO: Make it class Message.
239
223
  this.queue[message_id] = {
240
- ff,
224
+ msg, ff(x: any) {
225
+ ff(x)
226
+ // cleanup.
227
+ clearTimeout(this.timeout) // from this object!
228
+ delete queue[message_id]
229
+ },
241
230
  data_type: config.data_type,
242
231
  sent_time: config.timer ? Date.now() : null,
243
232
  timeout: sett(config.timeout, () => {
@@ -247,7 +236,7 @@ class WebSocketClient {
247
236
  'Websocket timeout expired: ': config.timeout,
248
237
  'for the message ': message_data
249
238
  })
250
- delete this.queue[message_id]
239
+ delete queue[message_id]
251
240
  }
252
241
  })
253
242
  }
package/src/types.ts CHANGED
@@ -55,4 +55,11 @@ declare namespace wsc {
55
55
  top: any
56
56
  data_type: DataType
57
57
  }
58
+
59
+ export interface Message {
60
+ msg: any, ff(x: any): any,
61
+ data_type: DataType,
62
+ sent_time: number | null,
63
+ timeout: NodeJS.Timeout
64
+ }
58
65
  }
package/src/utils.ts CHANGED
@@ -9,4 +9,10 @@ export const add_event = (o: wsc.Socket, e: string, handler: wsc.EventHandler) =
9
9
  export const sett = (
10
10
  a: number,
11
11
  b: { (): void; (...args: any[]): void; }
12
- ) => setTimeout(b, a)
12
+ ) => setTimeout(b, a)
13
+
14
+ export const try_splice = <T = any>(arr: T[], el: T) => {
15
+ const i = arr.indexOf(el)
16
+ if(~i) return arr.splice(arr.indexOf(el), 1)
17
+ else return []
18
+ }
package/test/index.ts CHANGED
@@ -11,10 +11,10 @@ import './specs/no-native-throws'
11
11
  import mockServer from './mock/server'
12
12
  import {test} from './suite'
13
13
 
14
- const {shutDown} = await mockServer()
14
+ const {shutDown, isRunning} = await mockServer()
15
15
  test.after(() => {
16
16
  setTimeout(async () => {
17
- await shutDown()
17
+ if(isRunning()) await shutDown()
18
18
  process.exit()
19
19
  }, 100)
20
20
  })
package/test/mock/WS.ts CHANGED
@@ -9,6 +9,7 @@ const createServer = (port = 40510) => new Promise<WebSocketServer>((ff, rj) =>
9
9
  server = new WebSocketServer({ port }, () => {
10
10
  server!.on('connection', (socket: WebSocket&{isAlive: boolean}) => {
11
11
  socket.on('message', (rawMessage: string) => {
12
+ // console.log({rawMessage: rawMessage.toString()})
12
13
  const {id, data} = JSON.parse(rawMessage)
13
14
  let response = ''
14
15
  if(data.shut) {
@@ -1,6 +1,6 @@
1
1
 
2
2
  import { WebSocketServer } from 'ws'
3
- import { createServer, killServer } from './WS.js'
3
+ import { createServer, killServer } from './WS'
4
4
 
5
5
  let port: number,
6
6
  server: WebSocketServer|null
@@ -12,6 +12,7 @@ export default async (new_port?: number) => {
12
12
  }
13
13
  return {
14
14
  server, port,
15
+ isRunning() {return Boolean(server)},
15
16
  shutDown: async () => { await killServer(); server=null }
16
17
  }
17
18
  }
@@ -1,6 +1,7 @@
1
1
  import { createNew } from '../utils'
2
2
  import mockServer from '../mock/server'
3
3
  import { test } from '../suite'
4
+ import { wait } from 'pepka'
4
5
 
5
6
  /** Rejects messages by timout */
6
7
  test('drops', () => new Promise(async (ff, rj) => {
@@ -8,23 +9,21 @@ test('drops', () => new Promise(async (ff, rj) => {
8
9
  const ws = createNew({timeout: 500}, port)
9
10
 
10
11
  await shutDown()
11
- const lauchServ = async () => await mockServer(port)
12
+ await wait(200)
12
13
 
13
- setTimeout(async () => {
14
- const msg = {echo: true, msg: 'hello!'}
15
- let to: NodeJS.Timeout
16
- try {
17
- to = setTimeout(() => {
18
- return rj()
19
- }, 600)
20
- await ws.send(msg)
21
- if(to) clearTimeout(to)
22
- await lauchServ()
14
+ const msg = {echo: true, msg: 'hello!'}
15
+ let to: NodeJS.Timeout
16
+ try {
17
+ to = setTimeout(() => {
23
18
  return rj()
24
- } catch(e) {
25
- if(to!) clearTimeout(to)
26
- await lauchServ()
27
- return ff()
28
- }
29
- }, 200)
19
+ }, 600)
20
+ await ws.send(msg)
21
+ if(to) clearTimeout(to)
22
+ await mockServer(port)
23
+ return rj()
24
+ } catch(e) {
25
+ if(to!) clearTimeout(to)
26
+ await mockServer(port)
27
+ return ff()
28
+ }
30
29
  }))
@@ -9,47 +9,45 @@ import { equals } from 'pepka'
9
9
  const addr = (port: number) => 'ws://localhost:' + port
10
10
 
11
11
  /** If an existing socket connection is provided via config. */
12
- test('existing_socket', () => {
13
- return new Promise(async (ff, rj) => {
14
- const {port} = await mockServer()
15
- const to = setTimeout(() => rj(), 4e4)
16
- const existing_addr = addr(port)
12
+ test('existing_socket', () => new Promise(async (ff, rj) => {
13
+ const {port} = await mockServer()
14
+ const to = setTimeout(() => rj(), 4e4)
15
+ const existing_addr = addr(port)
17
16
 
18
- // This one CANNOT connect as fast as we send to it,
19
- // So readyState is 0.
20
- const ws1 = createNew({socket: new WS(existing_addr)}, port)
17
+ // This one CANNOT connect as fast as we send to it,
18
+ // So readyState is 0.
19
+ const ws1 = createNew({socket: new WS(existing_addr)}, port)
21
20
 
22
- if(ws1.socket?.readyState !== 0) return rj('not ready.')
21
+ if(ws1.socket?.readyState !== 0) return rj('not ready.')
23
22
 
24
- const msg1 = {echo: true, msg: 'existing_socket!'}
25
- const response1 = await ws1.send(msg1)
23
+ const msg1 = {echo: true, msg: 'existing_socket!'}
24
+ const response1 = await ws1.send(msg1)
26
25
 
27
- if(
28
- ws1.socket?.readyState as number !== 1
29
- || !equals(response1, msg1)
30
- ) return rj('not ready.')
31
- await ws1.close()
26
+ if(
27
+ ws1.socket?.readyState as number !== 1
28
+ || !equals(response1, msg1)
29
+ ) return rj('not ready.')
30
+ await ws1.close()
32
31
 
33
- // This one DO CAN connect as fast as we send to it,
34
- // So readyState should be 1.
35
- const ws2_0 = new WS(existing_addr)
32
+ // This one DO CAN connect as fast as we send to it,
33
+ // So readyState should be 1.
34
+ const ws2_0 = new WS(existing_addr)
36
35
 
37
- ws2_0.addEventListener('open', async () => {
38
- const ws2 = await createNew({socket: ws2_0}, port)
36
+ ws2_0.addEventListener('open', async () => {
37
+ const ws2 = createNew({socket: ws2_0}, port)
39
38
 
40
- if(ws2.socket?.readyState !== 1) return rj('not ready.')
41
-
42
- const msg2 = {echo: true, msg: 'existing_socket!'}
43
- const response2 = await ws2.send(msg2)
39
+ if(ws2.socket?.readyState !== 1) return rj('not ready.')
40
+
41
+ const msg2 = {echo: true, msg: 'existing_socket!'}
42
+ const response2 = await ws2.send(msg2)
44
43
 
45
- if(
46
- ws2.socket?.readyState as number !== 1
47
- || !equals(response2, msg2)
48
- ) return rj('not ready.')
49
- await ws2.close()
44
+ if(
45
+ ws2.socket?.readyState as number !== 1
46
+ || !equals(response2, msg2)
47
+ ) return rj('not ready.')
48
+ await ws2.close()
50
49
 
51
- clearTimeout(to)
52
- ff()
53
- })
50
+ clearTimeout(to)
51
+ ff()
54
52
  })
55
- })
53
+ }))
@@ -1,22 +1,17 @@
1
1
  import { createNew, timeout } from '../utils'
2
2
  import mockServer from '../mock/server'
3
- import { equals } from 'pepka'
3
+ import { equals, wait } from 'pepka'
4
4
  import { test } from '../suite'
5
5
 
6
6
  /** Lazy connect */
7
- test('lazy', timeout(2e3, () => {
8
- return new Promise<void>(async (ff, rj) => {
9
- const {port} = await mockServer()
10
- const ws = createNew({ lazy: true }, port)
7
+ test('lazy', timeout(2e3, async () => {
8
+ const {port} = await mockServer()
9
+ const ws = createNew({ lazy: true }, port)
11
10
 
12
- setTimeout(async () => {
13
- if(ws.socket !== null) {
14
- rj()
15
- } else {
16
- const msg = {echo: true, msg: 'hello!'}
17
- const response = await ws.send(msg)
18
- if(equals(response, msg)) ff(); else rj()
19
- }
20
- }, 500)
21
- })
11
+ await wait(500)
12
+ if(ws.socket !== null) throw new Error('Socket is not open.')
13
+ else {
14
+ const msg = {echo: true, msg: 'hello!'}
15
+ if(!equals(await ws.send(msg), msg)) throw new Error('msg\s not equal.')
16
+ }
22
17
  }))
@@ -1,23 +1,41 @@
1
1
  import { createNew, timeout } from '../utils'
2
2
  import mockServer from '../mock/server'
3
- import { equals } from 'pepka'
3
+ import { equals, wait } from 'pepka'
4
4
  import { test } from '../suite'
5
5
 
6
6
  /** Reconnects if connection is broken. */
7
- test('reconnect', timeout(1e4, () => new Promise<void>(async (ff, rj) => {
8
- const {port, shutDown} = await mockServer()
9
- const ws = createNew({ reconnect: 1 }, port)
10
-
11
- setTimeout(async () => {
12
- await shutDown()
13
- setTimeout(async () => {
14
- await mockServer(port)
15
- setTimeout(async () => {
16
- const msg = {echo: true, msg: 'hello!'}
17
- const response = await ws.send(msg)
18
- if(equals(response, msg)) ff(); else rj('not equals.')
19
- }, 1500)
20
- }, 1100)
21
- }, 500)
22
- })
23
- ))
7
+ test('reconnect', timeout(1e4, () => async () => {
8
+ const {port, shutDown} = await mockServer()
9
+ const ws = createNew({ reconnect: 1 }, port)
10
+ await wait(200)
11
+ await shutDown()
12
+ await wait(500)
13
+ await mockServer(port)
14
+ await wait(600)
15
+ const msg = {echo: true, msg: 'hello!'}
16
+ const response = await ws.send(msg)
17
+ if(!equals(response, msg)) throw new Error('not equals.')
18
+ }))
19
+ /** Should send messages that were queued while being disconnected right after the reconnect. */
20
+ test('reconnect-queue', timeout(1e4, async () => {
21
+ const {port, shutDown} = await mockServer()
22
+ const ws = createNew({ reconnect: 1, timeout: 5e3 }, port)
23
+ await ws.ready()
24
+ await shutDown()
25
+ const msg1 = {echo: true, msg: 'hello!'}
26
+ const msg2 = {echo: true, msg: 'hello 2!'}
27
+ const msg3 = {echo: true, msg: 'hello 3!'}
28
+ let ok = false
29
+ const p = new Promise<void>((ff) => ws.send(msg1).then((res) => {
30
+ if(!equals(res, msg1)) throw new Error('msg1 not equals.')
31
+ else ws.send(msg2).then((res) => {
32
+ if(!equals(res, msg2)) throw new Error('msg2 not equals.')
33
+ else {ok=true}
34
+ ff()
35
+ })
36
+ }))
37
+ await mockServer(port)
38
+ await p
39
+ if(!ok) throw new Error('Not sent.')
40
+ if(!equals(await ws.send(msg3), msg3)) throw new Error('not sent or msg3 not equals.')
41
+ }))
package/test/utils.ts CHANGED
@@ -6,7 +6,7 @@ import WS from 'ws'
6
6
 
7
7
  export const createNew = (config = {}, port: number) => new WebSocketClient(Object.assign({
8
8
  url: 'ws://127.0.0.1:' + port,
9
- // log: (...a) => console.log(...a),
9
+ // log: (...a: any[]) => console.log(...a),
10
10
  adapter: (host: string, protocols?: string|string[]) => new (native_ws || WS)(host, protocols)
11
11
  }, config)
12
12
  )
@@ -15,12 +15,14 @@ export const createNew = (config = {}, port: number) => new WebSocketClient(Obje
15
15
  export const timeout = (time: number, handler: AnyFunc) => async (context: AnyObject) => {
16
16
  let timer: NodeJS.Timeout
17
17
  try {
18
- return await Promise.race([
18
+ await Promise.race([
19
19
  handler(context),
20
20
  new Promise((_resolve, reject) =>
21
21
  timer = setTimeout(() => reject(new Error('timeout')), time)
22
22
  )
23
23
  ])
24
+ } catch(e) {
25
+ throw e
24
26
  } finally {
25
27
  if(timer!) clearTimeout(timer)
26
28
  }
package/tsconfig.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "compilerOptions": {
3
- "moduleResolution": "Node",
3
+ "moduleResolution": "bundler",
4
4
  "lib": [ "esnext", "DOM" ],
5
5
  "strictNullChecks": true,
6
6
  "target": "esnext",
@@ -1,20 +0,0 @@
1
-
2
- version: 2
3
-
4
- jobs:
5
- build:
6
- working_directory: ~/test
7
- docker:
8
- - image: circleci/node
9
- steps:
10
- - checkout
11
- - run:
12
- name: install
13
- command: npm i
14
- - run:
15
- name: npm test
16
- command: |
17
- nodejs -v
18
- npm -v
19
- npm run lint
20
- npm run test:report
package/LAST_FEATURES.md DELETED
File without changes
package/_config.yml DELETED
@@ -1 +0,0 @@
1
- theme: jekyll-theme-cayman