wspromisify 2.6.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 +1 -1
- package/dist/bundle.d.ts +7 -1
- package/dist/bundle.mjs +1 -1
- package/package.json +8 -8
- package/src/WSC.ts +23 -34
- package/src/types.ts +7 -0
- package/src/utils.ts +7 -1
- package/test/index.ts +2 -2
- package/test/mock/WS.ts +1 -0
- package/test/mock/server.ts +2 -1
- package/test/specs/drops.ts +16 -17
- package/test/specs/existing_socket.ts +32 -34
- package/test/specs/lazy.ts +10 -15
- package/test/specs/reconnect.ts +36 -18
- package/test/utils.ts +4 -2
- package/tsconfig.json +1 -1
- package/.circleci/config.yml +0 -20
- package/LAST_FEATURES.md +0 -0
- package/_config.yml +0 -1
package/dist/bundle.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";const
|
|
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
|
|
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.
|
|
44
|
+
"version": "2.6.1",
|
|
45
45
|
"type": "module",
|
|
46
46
|
"exports": {
|
|
47
47
|
".": {
|
|
@@ -53,22 +53,22 @@
|
|
|
53
53
|
},
|
|
54
54
|
"devDependencies": {
|
|
55
55
|
"@rollup/plugin-commonjs": "^28.0.3",
|
|
56
|
-
"@rollup/plugin-node-resolve": "^16.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.
|
|
60
|
-
"@types/node": "^22.
|
|
61
|
-
"@types/ws": "^8.18.
|
|
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.
|
|
67
|
-
"rollup": "^4.
|
|
66
|
+
"pepka": "^1.6.3",
|
|
67
|
+
"rollup": "^4.40.0",
|
|
68
68
|
"rollup-plugin-typescript2": "^0.36.0",
|
|
69
69
|
"ts-node": "^10.9.2",
|
|
70
70
|
"tsx": "^4.19.3",
|
|
71
|
-
"typescript": "^5.8.
|
|
71
|
+
"typescript": "^5.8.3",
|
|
72
72
|
"uvu": "^0.5.6",
|
|
73
73
|
"ws": "^8.18.1"
|
|
74
74
|
},
|
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
|
-
|
|
33
|
-
this.
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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(
|
|
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
|
|
239
|
+
delete queue[message_id]
|
|
251
240
|
}
|
|
252
241
|
})
|
|
253
242
|
}
|
package/src/types.ts
CHANGED
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) {
|
package/test/mock/server.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
|
|
2
2
|
import { WebSocketServer } from 'ws'
|
|
3
|
-
import { createServer, killServer } from './WS
|
|
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
|
}
|
package/test/specs/drops.ts
CHANGED
|
@@ -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
|
-
|
|
12
|
+
await wait(200)
|
|
12
13
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
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
|
-
}
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
}
|
|
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
|
-
|
|
14
|
-
|
|
15
|
-
|
|
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
|
-
|
|
19
|
-
|
|
20
|
-
|
|
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
|
-
|
|
21
|
+
if(ws1.socket?.readyState !== 0) return rj('not ready.')
|
|
23
22
|
|
|
24
|
-
|
|
25
|
-
|
|
23
|
+
const msg1 = {echo: true, msg: 'existing_socket!'}
|
|
24
|
+
const response1 = await ws1.send(msg1)
|
|
26
25
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
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
|
-
|
|
34
|
-
|
|
35
|
-
|
|
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
|
-
|
|
38
|
-
|
|
36
|
+
ws2_0.addEventListener('open', async () => {
|
|
37
|
+
const ws2 = createNew({socket: ws2_0}, port)
|
|
39
38
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
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
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
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
|
-
|
|
52
|
-
|
|
53
|
-
})
|
|
50
|
+
clearTimeout(to)
|
|
51
|
+
ff()
|
|
54
52
|
})
|
|
55
|
-
})
|
|
53
|
+
}))
|
package/test/specs/lazy.ts
CHANGED
|
@@ -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
|
-
|
|
9
|
-
|
|
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
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
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
|
}))
|
package/test/specs/reconnect.ts
CHANGED
|
@@ -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, () =>
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
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
|
-
|
|
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
package/.circleci/config.yml
DELETED
|
@@ -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
|