wspromisify 2.5.0 → 2.6.1

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,c=0;for(;i&&c<s;c++)o[c]===e&&(o[c]=n[r-i],i--);for(c=s;i;c++,i--)o[c]=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 c=void 0,l=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:l))),v=k(0);S(1,l);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===c)(e))(n)?e:_((s=>s in n?z(e,S(1,l,t),n[s]):e),v)(t):n));z(c),_(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))),ce=G(((e,t,n)=>n.reduce(e,t))),le=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)=>ce(((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(le(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:[]};config={};init_flush(){this.queue={},this.messages=[]}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.handlers.open.forEach((t=>t(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.handlers.close.forEach((t=>t(...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.handlers.message.forEach((t=>t({...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}`)}}))}async 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);I(n,"error",we((t=>(this.log("error","status 3."),this.handlers.error.forEach((e=>e(t))),this.ws=null,e(3))))),n.readyState?(this.initSocket(n),e(null)):I(n,"open",we((()=>(this.log("open"),this.initSocket(n),e(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]&&(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.open=!1,this.reconnect_timeout=null,this.forcibly_closed=!1,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
@@ -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";
7
+ type WSEvent = "open" | "message" | "close" | "error" | "timeout";
8
8
  /** Minimal socket-like interface. */
9
9
  interface Socket {
10
10
  readyState: number;
@@ -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,12 +61,12 @@ 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;
61
67
  private config;
62
68
  private init_flush;
69
+ private call;
63
70
  private log;
64
71
  private initSocket;
65
72
  private connect;
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:[]};config={};init_flush(){this.queue={},this.messages=[]}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.handlers.open.forEach((t=>t(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.handlers.close.forEach((t=>t(...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.handlers.message.forEach((t=>t({...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}`)}}))}async 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);I(n,"error",we((t=>(this.log("error","status 3."),this.handlers.error.forEach((e=>e(t))),this.ws=null,e(3))))),n.readyState?(this.initSocket(n),e(null)):I(n,"open",we((()=>(this.log("open"),this.initSocket(n),e(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]&&(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.open=!1,this.reconnect_timeout=null,this.forcibly_closed=!1,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,48 +41,36 @@
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.5.0",
44
+ "version": "2.6.1",
45
45
  "type": "module",
46
46
  "exports": {
47
47
  ".": {
48
+ "types": "./dist/bundle.d.ts",
48
49
  "import": "./dist/bundle.mjs",
49
50
  "require": "./dist/bundle.cjs"
50
- }
51
- },
52
- "ava": {
53
- "extensions": {
54
- "js": true,
55
- "ts": "module"
56
51
  },
57
- "files": [
58
- "./test/specs/*.ts"
59
- ],
60
- "failFast": true,
61
- "timeout": "2m",
62
- "nodeArguments": [
63
- "--import=tsimp"
64
- ]
52
+ "./src": "./src/*"
65
53
  },
66
54
  "devDependencies": {
67
- "@rollup/plugin-commonjs": "^28.0.2",
68
- "@rollup/plugin-node-resolve": "^16.0.0",
55
+ "@rollup/plugin-commonjs": "^28.0.3",
56
+ "@rollup/plugin-node-resolve": "^16.0.1",
69
57
  "@rollup/plugin-replace": "^6.0.2",
70
58
  "@rollup/plugin-terser": "^0.4.4",
71
- "@types/express": "^5.0.0",
72
- "@types/node": "^22.13.1",
73
- "@types/ws": "^8.5.14",
59
+ "@types/express": "^5.0.1",
60
+ "@types/node": "^22.15.2",
61
+ "@types/ws": "^8.18.1",
74
62
  "codecov": "^3.8.3",
75
63
  "cross-env": "^7.0.3",
76
64
  "dts-bundle-generator": "^9.5.1",
77
65
  "nyc": "^17.1.0",
78
- "pepka": "^1.6.2",
79
- "rollup": "^4.34.2",
66
+ "pepka": "^1.6.3",
67
+ "rollup": "^4.40.0",
80
68
  "rollup-plugin-typescript2": "^0.36.0",
81
69
  "ts-node": "^10.9.2",
82
- "tsx": "^4.19.2",
83
- "typescript": "^5.7.3",
70
+ "tsx": "^4.19.3",
71
+ "typescript": "^5.8.3",
84
72
  "uvu": "^0.5.6",
85
- "ws": "^8.18.0"
73
+ "ws": "^8.18.1"
86
74
  },
87
75
  "types": "./dist/bundle.d.ts",
88
76
  "dependencies": {
package/src/WSC.ts CHANGED
@@ -2,28 +2,38 @@ 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()
9
9
 
10
+ type EventHandler<T extends keyof WebSocketEventMap> = AnyFunc<any, [WebSocketEventMap[T]]>
11
+ type EventHandlers = {
12
+ open: EventHandler<'open'>[]
13
+ close: EventHandler<'close'>[]
14
+ error: EventHandler<'error'>[]
15
+ message: AnyFunc<any, [WebSocketEventMap['message'] & {data: any}]>[]
16
+ timeout: AnyFunc<any, [data: any]>[]
17
+ }
18
+
10
19
  class WebSocketClient {
11
20
  private open = false
12
21
  private ws: wsc.Socket|null = null
13
22
  private forcibly_closed = false
14
23
  private reconnect_timeout: NodeJS.Timeout|null = null
15
- private queue = {}
16
- private messages: any[] = []
24
+ private queue: Record<string, wsc.Message> = {}
17
25
  private onReadyQueue: AnyFunc[] = []
18
26
  private onCloseQueue: AnyFunc[] = []
19
- private handlers = <{[event in wsc.WSEvent]: ((e: any) => void)[]}>{
20
- open: [], close: [], message: [], error: []
21
- }
27
+ private handlers: EventHandlers = { open: [], close: [], message: [], error: [], timeout: [] }
22
28
  private config = <wsc.Config>{}
23
29
 
24
30
  private init_flush(): void {
25
- this.queue = {} // data queuse
26
- this.messages = [] // send() queue
31
+ // TODO: reject them or save somehow ?..
32
+ qfilter(F, this.queue)
33
+ }
34
+ private call(event_name: wsc.WSEvent, ...args: any[]) {
35
+ // this.handlers.open[0]()
36
+ for(const h of this.handlers[event_name]) h(...args)
27
37
  }
28
38
 
29
39
  private log(event: string, message: any = null, time: number|null = null): void {
@@ -40,16 +50,14 @@ class WebSocketClient {
40
50
  }
41
51
 
42
52
  private initSocket(ws: wsc.Socket) {
43
- const config = this.config
53
+ const {queue, config} = this
44
54
  this.open = true
45
55
  this.onReadyQueue.forEach((fn: Function) => fn())
46
56
  this.onReadyQueue.splice(0)
47
57
  const {id_key, data_key} = config.server
48
58
  // Works also on previously opened sockets that do not fire 'open' event.
49
- this.handlers.open.forEach((h) => h(ws))
50
- // Send all pending messages.
51
- this.messages.forEach((message: any) => message.send())
52
- // It's reconnecting.
59
+ this.call('open', ws)
60
+ for(const msg_id in queue) ws.send(queue[msg_id].msg)
53
61
  if(this.reconnect_timeout !== null) {
54
62
  clearInterval(this.reconnect_timeout)
55
63
  this.reconnect_timeout = null
@@ -63,9 +71,10 @@ class WebSocketClient {
63
71
  add_event(ws, 'close', async (...e) => {
64
72
  this.log('close')
65
73
  this.open = false
74
+ this.ws = null
66
75
  this.onCloseQueue.forEach((fn: Function) => fn())
67
76
  this.onCloseQueue.splice(0)
68
- this.handlers.close.forEach((h: any) => h(...e))
77
+ this.call('close', ...e)
69
78
  // Auto reconnect.
70
79
  const reconnect = config.reconnect
71
80
  if(
@@ -81,15 +90,11 @@ class WebSocketClient {
81
90
  }
82
91
  // If some error occured, try again.
83
92
  const status = await this.connect()
84
- if(status !== null) {
93
+ if(status !== null)
85
94
  this.reconnect_timeout = setTimeout(reconnectFunc, reconnect * 1000)
86
- }
87
95
  }
88
- // No need for await.
96
+ // TODO: test normal close by server. Would it be infinite ?
89
97
  reconnectFunc()
90
- } else {
91
- this.ws = null
92
- this.open = false
93
98
  }
94
99
  // reset the flag to reuse.
95
100
  this.forcibly_closed = false
@@ -97,7 +102,7 @@ class WebSocketClient {
97
102
  add_event(ws, 'message', (e) => {
98
103
  try {
99
104
  const data = config.decode(e.data)
100
- this.handlers.message.forEach((h: any) => h({...e, data}))
105
+ this.call('message', {...e, data})
101
106
  if(data[id_key]) {
102
107
  const q = this.queue[data[id_key]]
103
108
  if(q) {
@@ -106,8 +111,6 @@ class WebSocketClient {
106
111
  this.log('message', data[data_key], time)
107
112
  // Play.
108
113
  q.ff(data[data_key])
109
- clearTimeout(q.timeout)
110
- delete this.queue[data[id_key]]
111
114
  }
112
115
  }
113
116
  } catch (err) {
@@ -116,7 +119,7 @@ class WebSocketClient {
116
119
  })
117
120
  }
118
121
 
119
- private async connect() { // returns status if won't open or null if ok.
122
+ private connect() { // returns status if won't open or null if ok.
120
123
  return new Promise((ff) => {
121
124
  if(this.open === true) {
122
125
  return ff(null)
@@ -124,48 +127,39 @@ class WebSocketClient {
124
127
  const config = this.config
125
128
  const ws = config.socket || config.adapter(config.url, config.protocols)
126
129
  this.ws = ws
127
-
128
130
  if(!ws || ws.readyState > 1) {
129
131
  this.ws = null
130
132
  this.log('error', 'ready() on closing or closed state! status 2.')
131
133
  return ff(2)
132
134
  }
133
-
135
+ const ffo = once(ff)
134
136
  add_event(ws, 'error', once((e) => {
135
- this.log('error', 'status 3.')
136
- this.handlers.error.forEach((h) => h(e))
137
+ this.log('error', 'status 3. Err: '+e.message)
138
+ this.call('error', e)
137
139
  this.ws = null
138
140
  // Some network error: Connection refused or so.
139
- return ff(3)
141
+ ffo(3)
140
142
  }))
141
143
  // Because 'open' won't be envoked on opened socket.
142
144
  if(ws.readyState) {
143
145
  this.initSocket(ws)
144
- ff(null)
146
+ ffo(null)
145
147
  } else {
146
148
  add_event(ws, 'open', once(() => {
147
149
  this.log('open')
148
150
  this.initSocket(ws)
149
- return ff(null)
151
+ ffo(null)
150
152
  }))
151
153
  }
152
154
  })
153
155
  }
154
-
155
- public get socket() {
156
- return this.ws
157
- }
158
-
156
+ public get socket() { return this.ws }
159
157
  public async ready() {
160
158
  return new Promise<void>((ff) => {
161
- if(this.open) {
162
- ff()
163
- } else {
164
- this.onReadyQueue.push(ff)
165
- }
159
+ if(this.open) ff()
160
+ else this.onReadyQueue.push(ff)
166
161
  })
167
162
  }
168
-
169
163
  public on(
170
164
  event_name: wsc.WSEvent,
171
165
  handler: (data: any) => any,
@@ -205,10 +199,9 @@ class WebSocketClient {
205
199
  opts = <wsc.SendOptions>{}
206
200
  ): Promise<ResponseDataType> {
207
201
  this.log('send', message_data)
208
- const config = this.config
202
+ const {config, ws, forcibly_closed, queue} = this
209
203
  const message = {}
210
204
  const data_key = config.server.data_key
211
- const first_time_lazy = config.lazy && !this.open
212
205
 
213
206
  const message_id = zipnum.zip((Math.random()*(MAX_32-10))|0)
214
207
  if(typeof opts.top === 'object') {
@@ -217,53 +210,44 @@ class WebSocketClient {
217
210
  }
218
211
  Object.assign(message, opts.top)
219
212
  }
213
+ config.pipes.forEach((pipe) => message_data = pipe(message_data))
220
214
 
221
- config.pipes.forEach(
222
- (pipe) => message_data = pipe(message_data)
223
- )
224
-
225
- if(this.open === true) {
226
- (this.ws as wsc.Socket).send(config.encode(message_id, message_data, config))
227
- } else if(this.open === false || first_time_lazy) {
228
- this.messages.push({
229
- send: () => (this.ws as wsc.Socket).send(config.encode(message_id, message_data, config))
230
- })
231
- if(first_time_lazy) {
232
- this.connect()
233
- }
234
- } else if(this.open === null) {
215
+ if(forcibly_closed)
235
216
  throw new Error('Attempting to send via closed WebSocket connection!')
236
- }
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)
237
221
 
238
222
  return new Promise((ff, rj) => {
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, () => {
244
233
  if(this.queue[message_id]) {
234
+ this.call('timeout', message_data)
245
235
  rj({
246
236
  'Websocket timeout expired: ': config.timeout,
247
237
  'for the message ': message_data
248
238
  })
249
- delete this.queue[message_id]
239
+ delete queue[message_id]
250
240
  }
251
241
  })
252
242
  }
253
243
  })
254
244
  }
255
245
 
246
+ // TODO: Add .on handlers to config!
256
247
  constructor(user_config: wsc.UserConfig = {}) {
257
248
  this.config = processConfig(user_config)
258
- // Init.
259
249
  this.init_flush()
260
- // Flags.
261
- this.open = false
262
- this.reconnect_timeout = null
263
- this.forcibly_closed = false
264
- if(!this.config.lazy) {
265
- this.connect()
266
- }
250
+ if(!this.config.lazy) this.connect()
267
251
  }
268
252
  }
269
253
 
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'
7
+ export type WSEvent = 'open' | 'message' | 'close' | 'error' | 'timeout'
8
8
 
9
9
  /** Minimal socket-like interface. */
10
10
  interface Socket {
@@ -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,6 +1,6 @@
1
1
  import mockServer from '../mock/server'
2
2
  import { test } from '../suite'
3
- import {WebSocketClient} from '../../src/WSC'
3
+ import WebSocketClient from '../../src/WSC'
4
4
 
5
5
  /** Ready method. */
6
6
  test('No native throws without an adapter', async () => {
@@ -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