wspromisify 2.5.0 → 2.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bundle.cjs +1 -1
- package/dist/bundle.d.ts +2 -1
- package/dist/bundle.mjs +1 -1
- package/package.json +10 -22
- package/src/WSC.ts +32 -37
- package/src/types.ts +1 -1
- package/test/specs/no-native-throws.ts +1 -1
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,
|
|
1
|
+
"use strict";const e=Symbol("Placeholder"),t=t=>{let n=0;for(const s of t)s!==e&&n++;return n},n=(t,n)=>{const s=t.length,o=t.slice(),r=n.length;let i=r,l=0;for(;i&&l<s;l++)o[l]===e&&(o[l]=n[r-i],i--);for(l=s;i;l++,i--)o[l]=n[r-i];return o},s=(e,o,r)=>{const i=e.length-o.length-t(r);if(i<1)return e(...n(o,r));{const t=(...t)=>s(e,n(o,r),t);return t.$args_left=i,t}},o=e=>(...n)=>e.length>t(n)?s(e,[],n):e(...n);function r(t){return function(n,s){const o=n===e,r=arguments.length;if(1===r&&o)throw new Error("Senseless placeholder usage.");return r>1?o?(t=>function(n){return n===e?t:t(n)})((e=>t(e,s))):t(n,s):e=>t(n,e)}}function i(e){return o(e)}const l=void 0,c=1/0,u=e=>typeof e,a=e=>null===e,h={u:"U",b:"B",n:"N",s:"S",f:"F"},f=Symbol(),d=e=>{const t=u(e);return"object"===t?a(e)?"Null":e.constructor.name:h[t[0]]+t.slice(1)},p=e=>e.length,g=r(((e,t)=>e===t)),m=r(((e,t)=>{const n=d(e);if(g(n,d(t))&&(g(n,"Object")||g(n,"Array"))){if(a(e)||a(t))return g(e,t);if(g(e,t))return!0;for(const n of[e,t])for(const s in n)if(!(g(n,t)&&s in e||g(n,e)&&s in t&&m(e[s],t[s])))return!1;return!0}return g(e,t)})),y=r(((e,t)=>(t.push(e),t))),w=i(((e,t,n)=>n.reduce(e,t))),b=o(((e,t,n,s)=>e(s)?t(s):n(s))),_=(...t)=>(...n)=>{let s,o=!0;for(let r=p(t)-1;r>-1;r--)o?(o=!1,s=t[r](...n)):s=s===e?t[r]():t[r](s);return s},k=r(((e,t)=>t[e])),S=i(((e,t,n)=>n.slice(e,(e=>"number"==u(e))(t)?t:c))),v=k(0);S(1,c);const E=r(((e,t)=>t.find(e))),P=e=>()=>e,W=r(((e,t)=>t.split(e))),j=P(!0),N=P(!1),q=r(((e,t)=>w(((t,n)=>E((t=>e(n,t)),t)?t:y(n,t)),[],t)))(m),z=i(((e,t,n)=>p(t)?(e=>a(e)||(e=>e===l)(e))(n)?e:_((s=>s in n?z(e,S(1,c,t),n[s]):e),v)(t):n));z(l),_(b(m(f),N,j),z(f));const Q=r(((e,t)=>t.map(e))),{floor:A}=Math,C="0123456789abcdefghijklmnopqrstuvwxyz",O=_((e=>Object.fromEntries(e)),Q(((e,t)=>[e,t])),W(""));class ${abc;abclen;c2pos;standard;setABC(e){if(!_(m(p(t=e)),p,q,W(""))(t))throw new Error("Not all chars are unique!");var t;this.abc=e,this.abclen=e.length,this.standard=C.startsWith(e),this.c2pos=O(e)}zip(e){const{abc:t,abclen:n}=this;let s="";for(;e>0;)s=t[e%n]+s,e=A(e/n);return s||"0"}unzip(e){const{standard:t,abclen:n,c2pos:s}=this;if(t)return parseInt(e,n);const o=e.length;let r=0;for(let t=0;t<o;t++)r+=s[e[t]]*n**(o-t-1);return r}constructor(e){this.setABC(e||C+"ABCDEFGHIJKLMNOPQRSTUVWXYZ")}}const B=new $;B.setABC.bind(B),B.zip.bind(B),B.unzip.bind(B);const R=(()=>{try{return WebSocket||null}catch{return null}})(),I=(e,t,n)=>e.addEventListener(t,n),T=(e,t)=>setTimeout(t,e),D={data_type:"json",log:()=>null,timer:!1,url:"localhost",timeout:1400,reconnect:2,lazy:!1,socket:null,adapter:(e,t)=>new WebSocket(e,t),encode:(e,t,{server:n})=>JSON.stringify({[n.id_key]:e,[n.data_key]:t}),decode:e=>JSON.parse(e),protocols:[],pipes:[],server:{id_key:"id",data_key:"data"},ping:{interval:55,content:{}}},U=Symbol("Placeholder"),x=e=>{let t=0;for(const n of e)n!==U&&t++;return t},F=(e,t)=>{const n=e.length,s=e.slice(),o=t.length;let r=o,i=0;for(;r&&i<n;i++)s[i]===U&&(s[i]=t[o-r],r--);for(i=n;r;i++,r--)s[i]=t[o-r];return s},J=(e,t,n)=>{const s=e.length-t.length-x(n);if(s<1)return e(...F(t,n));{const o=(...s)=>J(e,F(t,n),s);return o.$args_left=s,o}},L=e=>(...t)=>e.length>x(t)?J(e,[],t):e(...t);function M(e){return function(t,n){const s=t===U,o=arguments.length;if(1===o&&s)throw new Error("Senseless placeholder usage.");return o>1?s?(e=>function(t){return t===U?e:e(t)})((t=>e(t,n))):e(t,n):n=>e(t,n)}}function G(e){return L(e)}const H=void 0,K=1/0,V=e=>typeof e,X=e=>null===e,Y=e=>"number"==V(e),Z={u:"U",b:"B",n:"N",s:"S",f:"F"},ee=Symbol(),te=e=>{const t=V(e);return"object"===t?X(e)?"Null":e.constructor.name:Z[t[0]]+t.slice(1)},ne=e=>e.length,se=e=>X(e)||(e=>e===H)(e),oe=M(((e,t)=>e===t)),re=M(((e,t)=>{const n=te(e);if(oe(n,te(t))&&(oe(n,"Object")||oe(n,"Array"))){if(X(e)||X(t))return oe(e,t);if(oe(e,t))return!0;for(const n of[e,t])for(const s in n)if(!(oe(n,t)&&s in e||oe(n,e)&&s in t&&re(e[s],t[s])))return!1;return!0}return oe(e,t)})),ie=M(((e,t)=>(t.push(e),t))),le=G(((e,t,n)=>n.reduce(e,t))),ce=L(((e,t,n,s)=>e(s)?t(s):n(s))),ue=(...e)=>(...t)=>{let n,s=!0;for(let o=ne(e)-1;o>-1;o--)s?(s=!1,n=e[o](...t)):n=n===U?e[o]():e[o](n);return n},ae=M(((e,t)=>t[e])),he=G(((e,t,n)=>n.slice(e,Y(t)?t:K))),fe=ae(0);he(1,K);const de=M(((e,t)=>t.find(e))),pe=e=>()=>e,ge=pe(!0),me=pe(!1),ye=M(((e,t)=>le(((t,n)=>de((t=>e(n,t)),t)?t:ie(n,t)),[],t)));ye(re);const we=e=>{let t,n=!1;return(...s)=>n?t:(n=!0,t=e(...s))},be=G(((e,t,n)=>ne(t)?se(n)?e:ue((s=>s in n?be(e,he(1,K,t),n[s]):e),fe)(t):n));be(H),ue(ce(re(ee),me,ge),be(ee));const _e=new $;module.exports=class{open=!1;ws=null;forcibly_closed=!1;reconnect_timeout=null;queue={};messages=[];onReadyQueue=[];onCloseQueue=[];handlers={open:[],close:[],message:[],error:[],timeout:[]};config={};init_flush(){this.queue={},this.messages=[]}call(e,...t){for(const n of this.handlers[e])n(...t)}log(e,t=null,n=null){const s=this.config;null!==n?s.log(e,n,t):s.timer?s.log(e,null,t):s.log(e,t)}initSocket(e){const t=this.config;this.open=!0,this.onReadyQueue.forEach((e=>e())),this.onReadyQueue.splice(0);const{id_key:n,data_key:s}=t.server;if(this.call("open",e),this.messages.forEach((e=>e.send())),null!==this.reconnect_timeout&&(clearInterval(this.reconnect_timeout),this.reconnect_timeout=null),t.ping){const e=setInterval((()=>{this.open&&this.send(t.ping.content),this.forcibly_closed&&clearInterval(e)}),1e3*t.ping.interval)}I(e,"close",(async(...e)=>{this.log("close"),this.open=!1,this.onCloseQueue.forEach((e=>e())),this.onCloseQueue.splice(0),this.call("close",...e);const n=t.reconnect;if("number"!=typeof n||isNaN(n)||this.forcibly_closed)this.ws=null,this.open=!1;else{const e=async()=>{this.log("reconnect"),null!==this.ws&&(this.ws.close(),this.ws=null);null!==await this.connect()&&(this.reconnect_timeout=setTimeout(e,1e3*n))};e()}this.forcibly_closed=!1})),I(e,"message",(e=>{try{const o=t.decode(e.data);if(this.call("message",{...e,data:o}),o[n]){const e=this.queue[o[n]];if(e){const t=e.sent_time?Date.now()-e.sent_time:null;this.log("message",o[s],t),e.ff(o[s]),clearTimeout(e.timeout),delete this.queue[o[n]]}}}catch(t){console.error(t,`WSP: Decode error. Got: ${e.data}`)}}))}connect(){return new Promise((e=>{if(!0===this.open)return e(null);const t=this.config,n=t.socket||t.adapter(t.url,t.protocols);if(this.ws=n,!n||n.readyState>1)return this.ws=null,this.log("error","ready() on closing or closed state! status 2."),e(2);const s=we(e);I(n,"error",we((e=>{this.log("error","status 3."),this.call("error",e),this.ws=null,s(3)}))),n.readyState?(this.initSocket(n),s(null)):I(n,"open",we((()=>{this.log("open"),this.initSocket(n),s(null)})))}))}get socket(){return this.ws}async ready(){return new Promise((e=>{this.open?e():this.onReadyQueue.push(e)}))}on(e,t,n=ge,s=!1){const o=e=>n(e)&&t(e);return s?I(this.ws,e,o):this.handlers[e].push(o)}async close(){return new Promise(((e,t)=>{null===this.ws?t("WSP: closing a non-inited socket!"):(this.open=!1,this.onCloseQueue.push((()=>{this.init_flush(),this.ws=null,this.forcibly_closed=!0,e(null)})),this.ws.close())}))}async send(e,t={}){this.log("send",e);const n=this.config,s={},o=n.server.data_key,r=n.lazy&&!this.open,i=_e.zip(2147483637*Math.random()|0);if("object"==typeof t.top){if(t.top[o])throw new Error("Attempting to set data key/token via send() options!");Object.assign(s,t.top)}if(n.pipes.forEach((t=>e=t(e))),!0===this.open)this.ws.send(n.encode(i,e,n));else if(!1===this.open||r)this.messages.push({send:()=>this.ws.send(n.encode(i,e,n))}),r&&this.connect();else if(null===this.open)throw new Error("Attempting to send via closed WebSocket connection!");return new Promise(((t,s)=>{this.queue[i]={ff:t,data_type:n.data_type,sent_time:n.timer?Date.now():null,timeout:T(n.timeout,(()=>{this.queue[i]&&(this.call("timeout",e),s({"Websocket timeout expired: ":n.timeout,"for the message ":e}),delete this.queue[i])}))}}))}constructor(e={}){this.config=(e=>{if(null===R&&!("adapter"in e))throw new Error("\n This platform has no native WebSocket implementation.\n Please use 'ws' package as an adapter.\n See https://github.com/houd1ni/WebsocketPromisify/issues/23\n ");const t=Object.assign({},D,e),n=t.url;if("/"==n[0])try{const e=location.protocol.includes("s:")?"wss":"ws";t.url=`${e}://${location.hostname}:${location.port}${n}`}catch(e){throw new Error("WSP: URL starting with / in non-browser environment!")}return t})(e),this.init_flush(),this.config.lazy||this.connect()}};
|
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;
|
|
@@ -60,6 +60,7 @@ declare class WebSocketClient {
|
|
|
60
60
|
private handlers;
|
|
61
61
|
private config;
|
|
62
62
|
private init_flush;
|
|
63
|
+
private call;
|
|
63
64
|
private log;
|
|
64
65
|
private initSocket;
|
|
65
66
|
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.
|
|
1
|
+
const e=Symbol("Placeholder"),t=t=>{let n=0;for(const s of t)s!==e&&n++;return n},n=(t,n)=>{const s=t.length,o=t.slice(),r=n.length;let i=r,l=0;for(;i&&l<s;l++)o[l]===e&&(o[l]=n[r-i],i--);for(l=s;i;l++,i--)o[l]=n[r-i];return o},s=(e,o,r)=>{const i=e.length-o.length-t(r);if(i<1)return e(...n(o,r));{const t=(...t)=>s(e,n(o,r),t);return t.$args_left=i,t}},o=e=>(...n)=>e.length>t(n)?s(e,[],n):e(...n);function r(t){return function(n,s){const o=n===e,r=arguments.length;if(1===r&&o)throw new Error("Senseless placeholder usage.");return r>1?o?(t=>function(n){return n===e?t:t(n)})((e=>t(e,s))):t(n,s):e=>t(n,e)}}function i(e){return o(e)}const l=void 0,c=1/0,u=e=>typeof e,a=e=>null===e,h={u:"U",b:"B",n:"N",s:"S",f:"F"},f=Symbol(),d=e=>{const t=u(e);return"object"===t?a(e)?"Null":e.constructor.name:h[t[0]]+t.slice(1)},p=e=>e.length,g=r(((e,t)=>e===t)),m=r(((e,t)=>{const n=d(e);if(g(n,d(t))&&(g(n,"Object")||g(n,"Array"))){if(a(e)||a(t))return g(e,t);if(g(e,t))return!0;for(const n of[e,t])for(const s in n)if(!(g(n,t)&&s in e||g(n,e)&&s in t&&m(e[s],t[s])))return!1;return!0}return g(e,t)})),y=r(((e,t)=>(t.push(e),t))),w=i(((e,t,n)=>n.reduce(e,t))),b=o(((e,t,n,s)=>e(s)?t(s):n(s))),_=(...t)=>(...n)=>{let s,o=!0;for(let r=p(t)-1;r>-1;r--)o?(o=!1,s=t[r](...n)):s=s===e?t[r]():t[r](s);return s},k=r(((e,t)=>t[e])),S=i(((e,t,n)=>n.slice(e,(e=>"number"==u(e))(t)?t:c))),v=k(0);S(1,c);const E=r(((e,t)=>t.find(e))),P=e=>()=>e,W=r(((e,t)=>t.split(e))),j=P(!0),N=P(!1),q=r(((e,t)=>w(((t,n)=>E((t=>e(n,t)),t)?t:y(n,t)),[],t)))(m),z=i(((e,t,n)=>p(t)?(e=>a(e)||(e=>e===l)(e))(n)?e:_((s=>s in n?z(e,S(1,c,t),n[s]):e),v)(t):n));z(l),_(b(m(f),N,j),z(f));const Q=r(((e,t)=>t.map(e))),{floor:A}=Math,C="0123456789abcdefghijklmnopqrstuvwxyz",O=_((e=>Object.fromEntries(e)),Q(((e,t)=>[e,t])),W(""));class ${abc;abclen;c2pos;standard;setABC(e){if(!_(m(p(t=e)),p,q,W(""))(t))throw new Error("Not all chars are unique!");var t;this.abc=e,this.abclen=e.length,this.standard=C.startsWith(e),this.c2pos=O(e)}zip(e){const{abc:t,abclen:n}=this;let s="";for(;e>0;)s=t[e%n]+s,e=A(e/n);return s||"0"}unzip(e){const{standard:t,abclen:n,c2pos:s}=this;if(t)return parseInt(e,n);const o=e.length;let r=0;for(let t=0;t<o;t++)r+=s[e[t]]*n**(o-t-1);return r}constructor(e){this.setABC(e||C+"ABCDEFGHIJKLMNOPQRSTUVWXYZ")}}const B=new $;B.setABC.bind(B),B.zip.bind(B),B.unzip.bind(B);const R=(()=>{try{return WebSocket||null}catch{return null}})(),I=(e,t,n)=>e.addEventListener(t,n),T=(e,t)=>setTimeout(t,e),D={data_type:"json",log:()=>null,timer:!1,url:"localhost",timeout:1400,reconnect:2,lazy:!1,socket:null,adapter:(e,t)=>new WebSocket(e,t),encode:(e,t,{server:n})=>JSON.stringify({[n.id_key]:e,[n.data_key]:t}),decode:e=>JSON.parse(e),protocols:[],pipes:[],server:{id_key:"id",data_key:"data"},ping:{interval:55,content:{}}},U=Symbol("Placeholder"),x=e=>{let t=0;for(const n of e)n!==U&&t++;return t},F=(e,t)=>{const n=e.length,s=e.slice(),o=t.length;let r=o,i=0;for(;r&&i<n;i++)s[i]===U&&(s[i]=t[o-r],r--);for(i=n;r;i++,r--)s[i]=t[o-r];return s},J=(e,t,n)=>{const s=e.length-t.length-x(n);if(s<1)return e(...F(t,n));{const o=(...s)=>J(e,F(t,n),s);return o.$args_left=s,o}},L=e=>(...t)=>e.length>x(t)?J(e,[],t):e(...t);function M(e){return function(t,n){const s=t===U,o=arguments.length;if(1===o&&s)throw new Error("Senseless placeholder usage.");return o>1?s?(e=>function(t){return t===U?e:e(t)})((t=>e(t,n))):e(t,n):n=>e(t,n)}}function G(e){return L(e)}const H=void 0,K=1/0,V=e=>typeof e,X=e=>null===e,Y=e=>"number"==V(e),Z={u:"U",b:"B",n:"N",s:"S",f:"F"},ee=Symbol(),te=e=>{const t=V(e);return"object"===t?X(e)?"Null":e.constructor.name:Z[t[0]]+t.slice(1)},ne=e=>e.length,se=e=>X(e)||(e=>e===H)(e),oe=M(((e,t)=>e===t)),re=M(((e,t)=>{const n=te(e);if(oe(n,te(t))&&(oe(n,"Object")||oe(n,"Array"))){if(X(e)||X(t))return oe(e,t);if(oe(e,t))return!0;for(const n of[e,t])for(const s in n)if(!(oe(n,t)&&s in e||oe(n,e)&&s in t&&re(e[s],t[s])))return!1;return!0}return oe(e,t)})),ie=M(((e,t)=>(t.push(e),t))),le=G(((e,t,n)=>n.reduce(e,t))),ce=L(((e,t,n,s)=>e(s)?t(s):n(s))),ue=(...e)=>(...t)=>{let n,s=!0;for(let o=ne(e)-1;o>-1;o--)s?(s=!1,n=e[o](...t)):n=n===U?e[o]():e[o](n);return n},ae=M(((e,t)=>t[e])),he=G(((e,t,n)=>n.slice(e,Y(t)?t:K))),fe=ae(0);he(1,K);const de=M(((e,t)=>t.find(e))),pe=e=>()=>e,ge=pe(!0),me=pe(!1),ye=M(((e,t)=>le(((t,n)=>de((t=>e(n,t)),t)?t:ie(n,t)),[],t)));ye(re);const we=e=>{let t,n=!1;return(...s)=>n?t:(n=!0,t=e(...s))},be=G(((e,t,n)=>ne(t)?se(n)?e:ue((s=>s in n?be(e,he(1,K,t),n[s]):e),fe)(t):n));be(H),ue(ce(re(ee),me,ge),be(ee));const _e=new $;class ke{open=!1;ws=null;forcibly_closed=!1;reconnect_timeout=null;queue={};messages=[];onReadyQueue=[];onCloseQueue=[];handlers={open:[],close:[],message:[],error:[],timeout:[]};config={};init_flush(){this.queue={},this.messages=[]}call(e,...t){for(const n of this.handlers[e])n(...t)}log(e,t=null,n=null){const s=this.config;null!==n?s.log(e,n,t):s.timer?s.log(e,null,t):s.log(e,t)}initSocket(e){const t=this.config;this.open=!0,this.onReadyQueue.forEach((e=>e())),this.onReadyQueue.splice(0);const{id_key:n,data_key:s}=t.server;if(this.call("open",e),this.messages.forEach((e=>e.send())),null!==this.reconnect_timeout&&(clearInterval(this.reconnect_timeout),this.reconnect_timeout=null),t.ping){const e=setInterval((()=>{this.open&&this.send(t.ping.content),this.forcibly_closed&&clearInterval(e)}),1e3*t.ping.interval)}I(e,"close",(async(...e)=>{this.log("close"),this.open=!1,this.onCloseQueue.forEach((e=>e())),this.onCloseQueue.splice(0),this.call("close",...e);const n=t.reconnect;if("number"!=typeof n||isNaN(n)||this.forcibly_closed)this.ws=null,this.open=!1;else{const e=async()=>{this.log("reconnect"),null!==this.ws&&(this.ws.close(),this.ws=null);null!==await this.connect()&&(this.reconnect_timeout=setTimeout(e,1e3*n))};e()}this.forcibly_closed=!1})),I(e,"message",(e=>{try{const o=t.decode(e.data);if(this.call("message",{...e,data:o}),o[n]){const e=this.queue[o[n]];if(e){const t=e.sent_time?Date.now()-e.sent_time:null;this.log("message",o[s],t),e.ff(o[s]),clearTimeout(e.timeout),delete this.queue[o[n]]}}}catch(t){console.error(t,`WSP: Decode error. Got: ${e.data}`)}}))}connect(){return new Promise((e=>{if(!0===this.open)return e(null);const t=this.config,n=t.socket||t.adapter(t.url,t.protocols);if(this.ws=n,!n||n.readyState>1)return this.ws=null,this.log("error","ready() on closing or closed state! status 2."),e(2);const s=we(e);I(n,"error",we((e=>{this.log("error","status 3."),this.call("error",e),this.ws=null,s(3)}))),n.readyState?(this.initSocket(n),s(null)):I(n,"open",we((()=>{this.log("open"),this.initSocket(n),s(null)})))}))}get socket(){return this.ws}async ready(){return new Promise((e=>{this.open?e():this.onReadyQueue.push(e)}))}on(e,t,n=ge,s=!1){const o=e=>n(e)&&t(e);return s?I(this.ws,e,o):this.handlers[e].push(o)}async close(){return new Promise(((e,t)=>{null===this.ws?t("WSP: closing a non-inited socket!"):(this.open=!1,this.onCloseQueue.push((()=>{this.init_flush(),this.ws=null,this.forcibly_closed=!0,e(null)})),this.ws.close())}))}async send(e,t={}){this.log("send",e);const n=this.config,s={},o=n.server.data_key,r=n.lazy&&!this.open,i=_e.zip(2147483637*Math.random()|0);if("object"==typeof t.top){if(t.top[o])throw new Error("Attempting to set data key/token via send() options!");Object.assign(s,t.top)}if(n.pipes.forEach((t=>e=t(e))),!0===this.open)this.ws.send(n.encode(i,e,n));else if(!1===this.open||r)this.messages.push({send:()=>this.ws.send(n.encode(i,e,n))}),r&&this.connect();else if(null===this.open)throw new Error("Attempting to send via closed WebSocket connection!");return new Promise(((t,s)=>{this.queue[i]={ff:t,data_type:n.data_type,sent_time:n.timer?Date.now():null,timeout:T(n.timeout,(()=>{this.queue[i]&&(this.call("timeout",e),s({"Websocket timeout expired: ":n.timeout,"for the message ":e}),delete this.queue[i])}))}}))}constructor(e={}){this.config=(e=>{if(null===R&&!("adapter"in e))throw new Error("\n This platform has no native WebSocket implementation.\n Please use 'ws' package as an adapter.\n See https://github.com/houd1ni/WebsocketPromisify/issues/23\n ");const t=Object.assign({},D,e),n=t.url;if("/"==n[0])try{const e=location.protocol.includes("s:")?"wss":"ws";t.url=`${e}://${location.hostname}:${location.port}${n}`}catch(e){throw new Error("WSP: URL starting with / in non-browser environment!")}return t})(e),this.init_flush(),this.config.lazy||this.connect()}}export{ke as default};
|
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.
|
|
44
|
+
"version": "2.6.0",
|
|
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
|
-
"
|
|
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.
|
|
55
|
+
"@rollup/plugin-commonjs": "^28.0.3",
|
|
68
56
|
"@rollup/plugin-node-resolve": "^16.0.0",
|
|
69
57
|
"@rollup/plugin-replace": "^6.0.2",
|
|
70
58
|
"@rollup/plugin-terser": "^0.4.4",
|
|
71
59
|
"@types/express": "^5.0.0",
|
|
72
|
-
"@types/node": "^22.13.
|
|
73
|
-
"@types/ws": "^8.
|
|
60
|
+
"@types/node": "^22.13.9",
|
|
61
|
+
"@types/ws": "^8.18.0",
|
|
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
66
|
"pepka": "^1.6.2",
|
|
79
|
-
"rollup": "^4.34.
|
|
67
|
+
"rollup": "^4.34.9",
|
|
80
68
|
"rollup-plugin-typescript2": "^0.36.0",
|
|
81
69
|
"ts-node": "^10.9.2",
|
|
82
|
-
"tsx": "^4.19.
|
|
83
|
-
"typescript": "^5.
|
|
70
|
+
"tsx": "^4.19.3",
|
|
71
|
+
"typescript": "^5.8.2",
|
|
84
72
|
"uvu": "^0.5.6",
|
|
85
|
-
"ws": "^8.18.
|
|
73
|
+
"ws": "^8.18.1"
|
|
86
74
|
},
|
|
87
75
|
"types": "./dist/bundle.d.ts",
|
|
88
76
|
"dependencies": {
|
package/src/WSC.ts
CHANGED
|
@@ -7,6 +7,15 @@ import { AnyFunc, once, T } from 'pepka'
|
|
|
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
|
|
@@ -16,15 +25,17 @@ class WebSocketClient {
|
|
|
16
25
|
private messages: any[] = []
|
|
17
26
|
private onReadyQueue: AnyFunc[] = []
|
|
18
27
|
private onCloseQueue: AnyFunc[] = []
|
|
19
|
-
private handlers =
|
|
20
|
-
open: [], close: [], message: [], error: []
|
|
21
|
-
}
|
|
28
|
+
private handlers: EventHandlers = { open: [], close: [], message: [], error: [], timeout: [] }
|
|
22
29
|
private config = <wsc.Config>{}
|
|
23
30
|
|
|
24
31
|
private init_flush(): void {
|
|
25
32
|
this.queue = {} // data queuse
|
|
26
33
|
this.messages = [] // send() queue
|
|
27
34
|
}
|
|
35
|
+
private call(event_name: wsc.WSEvent, ...args: any[]) {
|
|
36
|
+
// this.handlers.open[0]()
|
|
37
|
+
for(const h of this.handlers[event_name]) h(...args)
|
|
38
|
+
}
|
|
28
39
|
|
|
29
40
|
private log(event: string, message: any = null, time: number|null = null): void {
|
|
30
41
|
const config = this.config
|
|
@@ -46,7 +57,7 @@ class WebSocketClient {
|
|
|
46
57
|
this.onReadyQueue.splice(0)
|
|
47
58
|
const {id_key, data_key} = config.server
|
|
48
59
|
// Works also on previously opened sockets that do not fire 'open' event.
|
|
49
|
-
this.
|
|
60
|
+
this.call('open', ws)
|
|
50
61
|
// Send all pending messages.
|
|
51
62
|
this.messages.forEach((message: any) => message.send())
|
|
52
63
|
// It's reconnecting.
|
|
@@ -65,7 +76,7 @@ class WebSocketClient {
|
|
|
65
76
|
this.open = false
|
|
66
77
|
this.onCloseQueue.forEach((fn: Function) => fn())
|
|
67
78
|
this.onCloseQueue.splice(0)
|
|
68
|
-
this.
|
|
79
|
+
this.call('close', ...e)
|
|
69
80
|
// Auto reconnect.
|
|
70
81
|
const reconnect = config.reconnect
|
|
71
82
|
if(
|
|
@@ -81,11 +92,10 @@ class WebSocketClient {
|
|
|
81
92
|
}
|
|
82
93
|
// If some error occured, try again.
|
|
83
94
|
const status = await this.connect()
|
|
84
|
-
if(status !== null)
|
|
95
|
+
if(status !== null)
|
|
85
96
|
this.reconnect_timeout = setTimeout(reconnectFunc, reconnect * 1000)
|
|
86
|
-
}
|
|
87
97
|
}
|
|
88
|
-
//
|
|
98
|
+
// TODO: test normal close by server. Would it be infinite ?
|
|
89
99
|
reconnectFunc()
|
|
90
100
|
} else {
|
|
91
101
|
this.ws = null
|
|
@@ -97,7 +107,7 @@ class WebSocketClient {
|
|
|
97
107
|
add_event(ws, 'message', (e) => {
|
|
98
108
|
try {
|
|
99
109
|
const data = config.decode(e.data)
|
|
100
|
-
this.
|
|
110
|
+
this.call('message', {...e, data})
|
|
101
111
|
if(data[id_key]) {
|
|
102
112
|
const q = this.queue[data[id_key]]
|
|
103
113
|
if(q) {
|
|
@@ -116,7 +126,7 @@ class WebSocketClient {
|
|
|
116
126
|
})
|
|
117
127
|
}
|
|
118
128
|
|
|
119
|
-
private
|
|
129
|
+
private connect() { // returns status if won't open or null if ok.
|
|
120
130
|
return new Promise((ff) => {
|
|
121
131
|
if(this.open === true) {
|
|
122
132
|
return ff(null)
|
|
@@ -124,38 +134,33 @@ class WebSocketClient {
|
|
|
124
134
|
const config = this.config
|
|
125
135
|
const ws = config.socket || config.adapter(config.url, config.protocols)
|
|
126
136
|
this.ws = ws
|
|
127
|
-
|
|
128
137
|
if(!ws || ws.readyState > 1) {
|
|
129
138
|
this.ws = null
|
|
130
139
|
this.log('error', 'ready() on closing or closed state! status 2.')
|
|
131
140
|
return ff(2)
|
|
132
141
|
}
|
|
133
|
-
|
|
142
|
+
const ffo = once(ff)
|
|
134
143
|
add_event(ws, 'error', once((e) => {
|
|
135
144
|
this.log('error', 'status 3.')
|
|
136
|
-
this.
|
|
145
|
+
this.call('error', e)
|
|
137
146
|
this.ws = null
|
|
138
147
|
// Some network error: Connection refused or so.
|
|
139
|
-
|
|
148
|
+
ffo(3)
|
|
140
149
|
}))
|
|
141
150
|
// Because 'open' won't be envoked on opened socket.
|
|
142
151
|
if(ws.readyState) {
|
|
143
152
|
this.initSocket(ws)
|
|
144
|
-
|
|
153
|
+
ffo(null)
|
|
145
154
|
} else {
|
|
146
155
|
add_event(ws, 'open', once(() => {
|
|
147
156
|
this.log('open')
|
|
148
157
|
this.initSocket(ws)
|
|
149
|
-
|
|
158
|
+
ffo(null)
|
|
150
159
|
}))
|
|
151
160
|
}
|
|
152
161
|
})
|
|
153
162
|
}
|
|
154
|
-
|
|
155
|
-
public get socket() {
|
|
156
|
-
return this.ws
|
|
157
|
-
}
|
|
158
|
-
|
|
163
|
+
public get socket() { return this.ws }
|
|
159
164
|
public async ready() {
|
|
160
165
|
return new Promise<void>((ff) => {
|
|
161
166
|
if(this.open) {
|
|
@@ -165,7 +170,6 @@ class WebSocketClient {
|
|
|
165
170
|
}
|
|
166
171
|
})
|
|
167
172
|
}
|
|
168
|
-
|
|
169
173
|
public on(
|
|
170
174
|
event_name: wsc.WSEvent,
|
|
171
175
|
handler: (data: any) => any,
|
|
@@ -217,10 +221,7 @@ class WebSocketClient {
|
|
|
217
221
|
}
|
|
218
222
|
Object.assign(message, opts.top)
|
|
219
223
|
}
|
|
220
|
-
|
|
221
|
-
config.pipes.forEach(
|
|
222
|
-
(pipe) => message_data = pipe(message_data)
|
|
223
|
-
)
|
|
224
|
+
config.pipes.forEach((pipe) => message_data = pipe(message_data))
|
|
224
225
|
|
|
225
226
|
if(this.open === true) {
|
|
226
227
|
(this.ws as wsc.Socket).send(config.encode(message_id, message_data, config))
|
|
@@ -228,20 +229,20 @@ class WebSocketClient {
|
|
|
228
229
|
this.messages.push({
|
|
229
230
|
send: () => (this.ws as wsc.Socket).send(config.encode(message_id, message_data, config))
|
|
230
231
|
})
|
|
231
|
-
if(first_time_lazy)
|
|
232
|
-
this.connect()
|
|
233
|
-
}
|
|
232
|
+
if(first_time_lazy) this.connect()
|
|
234
233
|
} else if(this.open === null) {
|
|
235
234
|
throw new Error('Attempting to send via closed WebSocket connection!')
|
|
236
235
|
}
|
|
237
236
|
|
|
238
237
|
return new Promise((ff, rj) => {
|
|
238
|
+
// TODO: Make it class Message.
|
|
239
239
|
this.queue[message_id] = {
|
|
240
240
|
ff,
|
|
241
241
|
data_type: config.data_type,
|
|
242
242
|
sent_time: config.timer ? Date.now() : null,
|
|
243
243
|
timeout: sett(config.timeout, () => {
|
|
244
244
|
if(this.queue[message_id]) {
|
|
245
|
+
this.call('timeout', message_data)
|
|
245
246
|
rj({
|
|
246
247
|
'Websocket timeout expired: ': config.timeout,
|
|
247
248
|
'for the message ': message_data
|
|
@@ -253,17 +254,11 @@ class WebSocketClient {
|
|
|
253
254
|
})
|
|
254
255
|
}
|
|
255
256
|
|
|
257
|
+
// TODO: Add .on handlers to config!
|
|
256
258
|
constructor(user_config: wsc.UserConfig = {}) {
|
|
257
259
|
this.config = processConfig(user_config)
|
|
258
|
-
// Init.
|
|
259
260
|
this.init_flush()
|
|
260
|
-
|
|
261
|
-
this.open = false
|
|
262
|
-
this.reconnect_timeout = null
|
|
263
|
-
this.forcibly_closed = false
|
|
264
|
-
if(!this.config.lazy) {
|
|
265
|
-
this.connect()
|
|
266
|
-
}
|
|
261
|
+
if(!this.config.lazy) this.connect()
|
|
267
262
|
}
|
|
268
263
|
}
|
|
269
264
|
|
package/src/types.ts
CHANGED