wspromisify
Advanced tools
Comparing version 2.3.0 to 2.4.0-beta.0
import './types'; | ||
declare const enrichConfig: (config: Partial<wsc.Config>) => wsc.Config; | ||
declare const enrichConfig: (config: wsc.UserConfig) => wsc.Config; | ||
export { enrichConfig }; |
@@ -5,2 +5,3 @@ declare namespace wsc { | ||
} | ||
type WSEvent = 'open' | 'message' | 'close' | 'error'; | ||
/** Minimal socket-like interface. */ | ||
@@ -38,2 +39,6 @@ interface Socket { | ||
}; | ||
ping: { | ||
interval: number; | ||
content: any; | ||
}; | ||
} | ||
@@ -40,0 +45,0 @@ type UserConfig = Partial<Config>; |
@@ -11,3 +11,3 @@ import './types'; | ||
private onCloseQueue; | ||
private messageHandlers; | ||
private handlers; | ||
private config; | ||
@@ -18,4 +18,4 @@ private init_flush; | ||
get socket(): any; | ||
ready(): Promise<unknown>; | ||
on(event_name: string, handler: (data: any) => any, predicate?: (data: any) => boolean, raw?: boolean): number | void; | ||
ready(): Promise<void>; | ||
on(event_name: wsc.WSEvent, handler: (data: any) => any, predicate?: (data: any) => boolean, raw?: boolean): number | void; | ||
close(): wsc.AsyncErrCode; | ||
@@ -22,0 +22,0 @@ send<RequestDataType = any, ResponseDataType = any>(message_data: RequestDataType, opts?: wsc.SendOptions): Promise<ResponseDataType>; |
/*! ***************************************************************************** | ||
Copyright (c) Microsoft Corporation. All rights reserved. | ||
Licensed under the Apache License, Version 2.0 (the "License"); you may not use | ||
this file except in compliance with the License. You may obtain a copy of the | ||
License at http://www.apache.org/licenses/LICENSE-2.0 | ||
Copyright (c) Microsoft Corporation. | ||
THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | ||
KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED | ||
WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, | ||
MERCHANTABLITY OR NON-INFRINGEMENT. | ||
Permission to use, copy, modify, and/or distribute this software for any | ||
purpose with or without fee is hereby granted. | ||
See the Apache Version 2.0 License for specific language governing permissions | ||
and limitations under the License. | ||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH | ||
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY | ||
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, | ||
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM | ||
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR | ||
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR | ||
PERFORMANCE OF THIS SOFTWARE. | ||
***************************************************************************** */ | ||
function t(t,e,s,n){return new(s||(s=Promise))((function(o,i){function l(t){try{c(n.next(t))}catch(t){i(t)}}function r(t){try{c(n.throw(t))}catch(t){i(t)}}function c(t){t.done?o(t.value):new s((function(e){e(t.value)})).then(l,r)}c((n=n.apply(t,e||[])).next())}))}const e="0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ",s=e.length-1;const n=(t,e,s)=>t.addEventListener(e,s),o=t=>{let e=!1,s=null;return(...n)=>e?s:(e=!0,s=t(...n))},i=function(e){const s=this.config;this.open=!0,this.onReadyQueue.forEach(t=>t()),this.onReadyQueue.splice(0);const{id_key:o,data_key:i}=s.server;this.messages.forEach(t=>t.send()),null!==this.reconnect_timeout&&(clearInterval(this.reconnect_timeout),this.reconnect_timeout=null),n(e,"close",()=>t(this,void 0,void 0,(function*(){this.log("close"),this.open=!1,this.onCloseQueue.forEach(t=>t()),this.onCloseQueue=[];const e=s.reconnect;if("number"!=typeof e||isNaN(e)||this.forcibly_closed)this.ws=null,this.open=null;else{const s=()=>t(this,void 0,void 0,(function*(){this.log("reconnect"),null!==this.ws&&(this.ws.close(),this.ws=null),null!==(yield this.connect())&&(this.reconnect_timeout=setTimeout(s,1e3*e))}));s()}this.forcibly_closed=!1}))),n(e,"message",t=>{try{const e=s.decode(t.data);if(this.messageHandlers.forEach(s=>s(Object.assign(Object.assign({},t),{data:e}))),e[o]){const t=this.queue[e[o]];if(t){const s=t.sent_time?Date.now()-t.sent_time:null;this.log("message",e[i],s),t.ff(e[i]),clearTimeout(t.timeout),delete this.queue[e[o]]}}}catch(e){console.error(e,`WSP: Decode error. Got: ${t.data}`)}})},l=function(t){if(!0===this.open)return t(null);const e=this.config,s=e.socket||e.adapter(e.url,e.protocols);if(this.ws=s,!s||s.readyState>1)return this.ws=null,this.log("error","ready() on closing or closed state! status 2."),t(2);n(s,"error",o(()=>(this.ws=null,this.log("error","status 3."),t(3)))),s.readyState?(i.call(this,s),t(null)):n(s,"open",o(()=>(this.log("open"),i.call(this,s),t(null))))},r={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:s})=>JSON.stringify({[s.id_key]:t,[s.data_key]:e}),decode:t=>JSON.parse(t),protocols:[],pipes:[],server:{id_key:"id",data_key:"data"}};var c=function(){return!0};const u=Math.pow(2,31)-1;export default class{constructor(t={}){this.open=null,this.ws=null,this.forcibly_closed=!1,this.reconnect_timeout=null,this.queue={},this.messages=[],this.onReadyQueue=[],this.onCloseQueue=[],this.messageHandlers=[],this.config={},this.config=(t=>{const e=Object.assign({},r,t),s=e.url;if("/"==s[0])try{const t=location.protocol.includes("s:")?"wss":"ws";e.url=`${t}://${location.hostname}:${location.port}${s}`}catch(t){throw new Error("WSP: URL starting with / in non-browser environment!")}return e})(t),this.init_flush(),this.open=!1,this.reconnect_timeout=null,this.forcibly_closed=!1,this.config.lazy||this.connect()}init_flush(){this.queue={},this.messages=[]}log(t,e=null,s=null){const n=this.config;null!==s?n.log(t,s,e):n.timer?n.log(t,null,e):n.log(t,e)}connect(){return t(this,void 0,void 0,(function*(){return new Promise(t=>{l.call(this,t)})}))}get socket(){return this.ws}ready(){return t(this,void 0,void 0,(function*(){return new Promise(t=>{this.open?t():this.onReadyQueue.push(t)})}))}on(t,e,s=c,o=!1){const i=t=>s(t)&&e(t);return o||"message"!==t?n(this.ws,t,i):this.messageHandlers.push(i)}close(){return t(this,void 0,void 0,(function*(){return new Promise((t,e)=>{null===this.ws?e("WSP: closing a non-inited socket!"):(this.open=null,this.onCloseQueue.push(()=>{this.init_flush(),this.ws=null,this.forcibly_closed=!0,t(null)}),this.ws.close())})}))}send(n,o={}){return t(this,void 0,void 0,(function*(){this.log("send",n);const t=this.config,i={},l=t.server.data_key,r=t.lazy&&!this.open,c=(t=>{const n=[];for(;t>=1;)n.push(e[t%(s+1)]),t=t/s|0;return n.join("")})(Math.random()*(u-10)|0);if("object"==typeof o.top){if(o.top[l])throw new Error("Attempting to set data key/token via send() options!");Object.assign(i,o.top)}if(t.pipes.forEach(t=>n=t(n)),!0===this.open)this.ws.send(t.encode(c,n,t));else if(!1===this.open||r)this.messages.push({send:()=>this.ws.send(t.encode(c,n,t))}),r&&this.connect();else if(null===this.open)throw new Error("Attempting to send via closed WebSocket connection!");return new Promise((e,s)=>{var n,o;this.queue[c]={ff:e,data_type:t.data_type,sent_time:t.timer?Date.now():null,timeout:(n=t.timeout,o=()=>{this.queue[c]&&(s({"Websocket timeout expired: ":t.timeout,"for the message":i}),delete this.queue[c])},setTimeout(o,n))}})}))}} | ||
function t(t,e,s,n){return new(s||(s=Promise))((function(o,i){function r(t){try{c(n.next(t))}catch(t){i(t)}}function l(t){try{c(n.throw(t))}catch(t){i(t)}}function c(t){var e;t.done?o(t.value):(e=t.value,e instanceof s?e:new s((function(t){t(e)}))).then(r,l)}c((n=n.apply(t,e||[])).next())}))}const e="0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ",s=e.length-1;const n=(t,e,s)=>t.addEventListener(e,s),o=t=>{let e=!1,s=null;return(...n)=>e?s:(e=!0,s=t(...n))},i=function(e){const s=this.config;this.open=!0,this.onReadyQueue.forEach((t=>t())),this.onReadyQueue.splice(0);const{id_key:o,data_key:i}=s.server;if(this.handlers.open.forEach((t=>t())),this.messages.forEach((t=>t.send())),null!==this.reconnect_timeout&&(clearInterval(this.reconnect_timeout),this.reconnect_timeout=null),s.ping){const t=setInterval((()=>{this.open&&this.send(s.ping.content),this.forcibly_closed&&clearInterval(t)}),s.ping.interval)}n(e,"close",(()=>t(this,void 0,void 0,(function*(){this.log("close"),this.open=!1,this.onCloseQueue.forEach((t=>t())),this.onCloseQueue=[];const e=s.reconnect;if("number"!=typeof e||isNaN(e)||this.forcibly_closed)this.ws=null,this.open=null;else{const s=()=>t(this,void 0,void 0,(function*(){this.log("reconnect"),null!==this.ws&&(this.ws.close(),this.ws=null);null!==(yield this.connect())&&(this.reconnect_timeout=setTimeout(s,1e3*e))}));s()}this.forcibly_closed=!1})))),n(e,"message",(t=>{try{const e=s.decode(t.data);if(this.handlers.message.forEach((s=>s(Object.assign(Object.assign({},t),{data:e})))),e[o]){const t=this.queue[e[o]];if(t){const s=t.sent_time?Date.now()-t.sent_time:null;this.log("message",e[i],s),t.ff(e[i]),clearTimeout(t.timeout),delete this.queue[e[o]]}}}catch(e){console.error(e,`WSP: Decode error. Got: ${t.data}`)}}))},r=function(t){if(!0===this.open)return t(null);const e=this.config,s=e.socket||e.adapter(e.url,e.protocols);if(this.ws=s,!s||s.readyState>1)return this.ws=null,this.log("error","ready() on closing or closed state! status 2."),t(2);n(s,"error",o((e=>(this.log("error","status 3."),this.handlers.error.forEach((t=>t(e))),this.ws=null,t(3))))),s.readyState?(i.call(this,s),t(null)):n(s,"open",o((()=>(this.log("open"),i.call(this,s),t(null)))))},l={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:s})=>JSON.stringify({[s.id_key]:t,[s.data_key]:e}),decode:t=>JSON.parse(t),protocols:[],pipes:[],server:{id_key:"id",data_key:"data"},ping:{interval:55,content:{}}};var c=function(){return!0};const h=Math.pow(2,31)-1;export default class{constructor(t={}){this.open=null,this.ws=null,this.forcibly_closed=!1,this.reconnect_timeout=null,this.queue={},this.messages=[],this.onReadyQueue=[],this.onCloseQueue=[],this.handlers={open:[],message:[],close:[],error:[]},this.config={},this.config=(t=>{const e=Object.assign({},l,t),s=e.url;if("/"==s[0])try{const t=location.protocol.includes("s:")?"wss":"ws";e.url=`${t}://${location.hostname}:${location.port}${s}`}catch(t){throw new Error("WSP: URL starting with / in non-browser environment!")}return e})(t),this.init_flush(),this.open=!1,this.reconnect_timeout=null,this.forcibly_closed=!1,this.config.lazy||this.connect()}init_flush(){this.queue={},this.messages=[]}log(t,e=null,s=null){const n=this.config;null!==s?n.log(t,s,e):n.timer?n.log(t,null,e):n.log(t,e)}connect(){return t(this,void 0,void 0,(function*(){return new Promise((t=>{r.call(this,t)}))}))}get socket(){return this.ws}ready(){return t(this,void 0,void 0,(function*(){return new Promise((t=>{this.open?t():this.onReadyQueue.push(t)}))}))}on(t,e,s=c,o=!1){const i=t=>s(t)&&e(t);return o?n(this.ws,t,i):this.handlers[t].push(i)}close(){return t(this,void 0,void 0,(function*(){return new Promise(((t,e)=>{null===this.ws?e("WSP: closing a non-inited socket!"):(this.open=null,this.onCloseQueue.push((()=>{this.init_flush(),this.ws=null,this.forcibly_closed=!0,t(null)})),this.ws.close())}))}))}send(n,o={}){return t(this,void 0,void 0,(function*(){this.log("send",n);const t=this.config,i={},r=t.server.data_key,l=t.lazy&&!this.open,c=(t=>{const n=[];for(;t>=1;)n.push(e[t%(s+1)]),t=t/s|0;return n.join("")})(Math.random()*(h-10)|0);if("object"==typeof o.top){if(o.top[r])throw new Error("Attempting to set data key/token via send() options!");Object.assign(i,o.top)}if(t.pipes.forEach((t=>n=t(n))),!0===this.open)this.ws.send(t.encode(c,n,t));else if(!1===this.open||l)this.messages.push({send:()=>this.ws.send(t.encode(c,n,t))}),l&&this.connect();else if(null===this.open)throw new Error("Attempting to send via closed WebSocket connection!");return new Promise(((e,s)=>{var n,o;this.queue[c]={ff:e,data_type:t.data_type,sent_time:t.timer?Date.now():null,timeout:(n=t.timeout,o=()=>{this.queue[c]&&(s({"Websocket timeout expired: ":t.timeout,"for the message":i}),delete this.queue[c])},setTimeout(o,n))}}))}))}} |
"use strict"; | ||
/*! ***************************************************************************** | ||
Copyright (c) Microsoft Corporation. All rights reserved. | ||
Licensed under the Apache License, Version 2.0 (the "License"); you may not use | ||
this file except in compliance with the License. You may obtain a copy of the | ||
License at http://www.apache.org/licenses/LICENSE-2.0 | ||
Copyright (c) Microsoft Corporation. | ||
THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | ||
KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED | ||
WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, | ||
MERCHANTABLITY OR NON-INFRINGEMENT. | ||
Permission to use, copy, modify, and/or distribute this software for any | ||
purpose with or without fee is hereby granted. | ||
See the Apache Version 2.0 License for specific language governing permissions | ||
and limitations under the License. | ||
***************************************************************************** */function t(t,e,s,n){return new(s||(s=Promise))((function(o,i){function l(t){try{c(n.next(t))}catch(t){i(t)}}function r(t){try{c(n.throw(t))}catch(t){i(t)}}function c(t){t.done?o(t.value):new s((function(e){e(t.value)})).then(l,r)}c((n=n.apply(t,e||[])).next())}))}const e="0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ",s=e.length-1;const n=(t,e,s)=>t.addEventListener(e,s),o=t=>{let e=!1,s=null;return(...n)=>e?s:(e=!0,s=t(...n))},i=function(e){const s=this.config;this.open=!0,this.onReadyQueue.forEach(t=>t()),this.onReadyQueue.splice(0);const{id_key:o,data_key:i}=s.server;this.messages.forEach(t=>t.send()),null!==this.reconnect_timeout&&(clearInterval(this.reconnect_timeout),this.reconnect_timeout=null),n(e,"close",()=>t(this,void 0,void 0,(function*(){this.log("close"),this.open=!1,this.onCloseQueue.forEach(t=>t()),this.onCloseQueue=[];const e=s.reconnect;if("number"!=typeof e||isNaN(e)||this.forcibly_closed)this.ws=null,this.open=null;else{const s=()=>t(this,void 0,void 0,(function*(){this.log("reconnect"),null!==this.ws&&(this.ws.close(),this.ws=null),null!==(yield this.connect())&&(this.reconnect_timeout=setTimeout(s,1e3*e))}));s()}this.forcibly_closed=!1}))),n(e,"message",t=>{try{const e=s.decode(t.data);if(this.messageHandlers.forEach(s=>s(Object.assign(Object.assign({},t),{data:e}))),e[o]){const t=this.queue[e[o]];if(t){const s=t.sent_time?Date.now()-t.sent_time:null;this.log("message",e[i],s),t.ff(e[i]),clearTimeout(t.timeout),delete this.queue[e[o]]}}}catch(e){console.error(e,`WSP: Decode error. Got: ${t.data}`)}})},l=function(t){if(!0===this.open)return t(null);const e=this.config,s=e.socket||e.adapter(e.url,e.protocols);if(this.ws=s,!s||s.readyState>1)return this.ws=null,this.log("error","ready() on closing or closed state! status 2."),t(2);n(s,"error",o(()=>(this.ws=null,this.log("error","status 3."),t(3)))),s.readyState?(i.call(this,s),t(null)):n(s,"open",o(()=>(this.log("open"),i.call(this,s),t(null))))},r={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:s})=>JSON.stringify({[s.id_key]:t,[s.data_key]:e}),decode:t=>JSON.parse(t),protocols:[],pipes:[],server:{id_key:"id",data_key:"data"}};var c=function(){return!0};const u=Math.pow(2,31)-1;module.exports=class{constructor(t={}){this.open=null,this.ws=null,this.forcibly_closed=!1,this.reconnect_timeout=null,this.queue={},this.messages=[],this.onReadyQueue=[],this.onCloseQueue=[],this.messageHandlers=[],this.config={},this.config=(t=>{const e=Object.assign({},r,t),s=e.url;if("/"==s[0])try{const t=location.protocol.includes("s:")?"wss":"ws";e.url=`${t}://${location.hostname}:${location.port}${s}`}catch(t){throw new Error("WSP: URL starting with / in non-browser environment!")}return e})(t),this.init_flush(),this.open=!1,this.reconnect_timeout=null,this.forcibly_closed=!1,this.config.lazy||this.connect()}init_flush(){this.queue={},this.messages=[]}log(t,e=null,s=null){const n=this.config;null!==s?n.log(t,s,e):n.timer?n.log(t,null,e):n.log(t,e)}connect(){return t(this,void 0,void 0,(function*(){return new Promise(t=>{l.call(this,t)})}))}get socket(){return this.ws}ready(){return t(this,void 0,void 0,(function*(){return new Promise(t=>{this.open?t():this.onReadyQueue.push(t)})}))}on(t,e,s=c,o=!1){const i=t=>s(t)&&e(t);return o||"message"!==t?n(this.ws,t,i):this.messageHandlers.push(i)}close(){return t(this,void 0,void 0,(function*(){return new Promise((t,e)=>{null===this.ws?e("WSP: closing a non-inited socket!"):(this.open=null,this.onCloseQueue.push(()=>{this.init_flush(),this.ws=null,this.forcibly_closed=!0,t(null)}),this.ws.close())})}))}send(n,o={}){return t(this,void 0,void 0,(function*(){this.log("send",n);const t=this.config,i={},l=t.server.data_key,r=t.lazy&&!this.open,c=(t=>{const n=[];for(;t>=1;)n.push(e[t%(s+1)]),t=t/s|0;return n.join("")})(Math.random()*(u-10)|0);if("object"==typeof o.top){if(o.top[l])throw new Error("Attempting to set data key/token via send() options!");Object.assign(i,o.top)}if(t.pipes.forEach(t=>n=t(n)),!0===this.open)this.ws.send(t.encode(c,n,t));else if(!1===this.open||r)this.messages.push({send:()=>this.ws.send(t.encode(c,n,t))}),r&&this.connect();else if(null===this.open)throw new Error("Attempting to send via closed WebSocket connection!");return new Promise((e,s)=>{var n,o;this.queue[c]={ff:e,data_type:t.data_type,sent_time:t.timer?Date.now():null,timeout:(n=t.timeout,o=()=>{this.queue[c]&&(s({"Websocket timeout expired: ":t.timeout,"for the message":i}),delete this.queue[c])},setTimeout(o,n))}})}))}}; | ||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH | ||
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY | ||
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, | ||
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM | ||
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR | ||
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR | ||
PERFORMANCE OF THIS SOFTWARE. | ||
***************************************************************************** */function t(t,e,s,n){return new(s||(s=Promise))((function(o,i){function r(t){try{c(n.next(t))}catch(t){i(t)}}function l(t){try{c(n.throw(t))}catch(t){i(t)}}function c(t){var e;t.done?o(t.value):(e=t.value,e instanceof s?e:new s((function(t){t(e)}))).then(r,l)}c((n=n.apply(t,e||[])).next())}))}const e="0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ",s=e.length-1;const n=(t,e,s)=>t.addEventListener(e,s),o=t=>{let e=!1,s=null;return(...n)=>e?s:(e=!0,s=t(...n))},i=function(e){const s=this.config;this.open=!0,this.onReadyQueue.forEach((t=>t())),this.onReadyQueue.splice(0);const{id_key:o,data_key:i}=s.server;if(this.handlers.open.forEach((t=>t())),this.messages.forEach((t=>t.send())),null!==this.reconnect_timeout&&(clearInterval(this.reconnect_timeout),this.reconnect_timeout=null),s.ping){const t=setInterval((()=>{this.open&&this.send(s.ping.content),this.forcibly_closed&&clearInterval(t)}),s.ping.interval)}n(e,"close",(()=>t(this,void 0,void 0,(function*(){this.log("close"),this.open=!1,this.onCloseQueue.forEach((t=>t())),this.onCloseQueue=[];const e=s.reconnect;if("number"!=typeof e||isNaN(e)||this.forcibly_closed)this.ws=null,this.open=null;else{const s=()=>t(this,void 0,void 0,(function*(){this.log("reconnect"),null!==this.ws&&(this.ws.close(),this.ws=null);null!==(yield this.connect())&&(this.reconnect_timeout=setTimeout(s,1e3*e))}));s()}this.forcibly_closed=!1})))),n(e,"message",(t=>{try{const e=s.decode(t.data);if(this.handlers.message.forEach((s=>s(Object.assign(Object.assign({},t),{data:e})))),e[o]){const t=this.queue[e[o]];if(t){const s=t.sent_time?Date.now()-t.sent_time:null;this.log("message",e[i],s),t.ff(e[i]),clearTimeout(t.timeout),delete this.queue[e[o]]}}}catch(e){console.error(e,`WSP: Decode error. Got: ${t.data}`)}}))},r=function(t){if(!0===this.open)return t(null);const e=this.config,s=e.socket||e.adapter(e.url,e.protocols);if(this.ws=s,!s||s.readyState>1)return this.ws=null,this.log("error","ready() on closing or closed state! status 2."),t(2);n(s,"error",o((e=>(this.log("error","status 3."),this.handlers.error.forEach((t=>t(e))),this.ws=null,t(3))))),s.readyState?(i.call(this,s),t(null)):n(s,"open",o((()=>(this.log("open"),i.call(this,s),t(null)))))},l={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:s})=>JSON.stringify({[s.id_key]:t,[s.data_key]:e}),decode:t=>JSON.parse(t),protocols:[],pipes:[],server:{id_key:"id",data_key:"data"},ping:{interval:55,content:{}}};var c=function(){return!0};const h=Math.pow(2,31)-1;module.exports=class{constructor(t={}){this.open=null,this.ws=null,this.forcibly_closed=!1,this.reconnect_timeout=null,this.queue={},this.messages=[],this.onReadyQueue=[],this.onCloseQueue=[],this.handlers={open:[],message:[],close:[],error:[]},this.config={},this.config=(t=>{const e=Object.assign({},l,t),s=e.url;if("/"==s[0])try{const t=location.protocol.includes("s:")?"wss":"ws";e.url=`${t}://${location.hostname}:${location.port}${s}`}catch(t){throw new Error("WSP: URL starting with / in non-browser environment!")}return e})(t),this.init_flush(),this.open=!1,this.reconnect_timeout=null,this.forcibly_closed=!1,this.config.lazy||this.connect()}init_flush(){this.queue={},this.messages=[]}log(t,e=null,s=null){const n=this.config;null!==s?n.log(t,s,e):n.timer?n.log(t,null,e):n.log(t,e)}connect(){return t(this,void 0,void 0,(function*(){return new Promise((t=>{r.call(this,t)}))}))}get socket(){return this.ws}ready(){return t(this,void 0,void 0,(function*(){return new Promise((t=>{this.open?t():this.onReadyQueue.push(t)}))}))}on(t,e,s=c,o=!1){const i=t=>s(t)&&e(t);return o?n(this.ws,t,i):this.handlers[t].push(i)}close(){return t(this,void 0,void 0,(function*(){return new Promise(((t,e)=>{null===this.ws?e("WSP: closing a non-inited socket!"):(this.open=null,this.onCloseQueue.push((()=>{this.init_flush(),this.ws=null,this.forcibly_closed=!0,t(null)})),this.ws.close())}))}))}send(n,o={}){return t(this,void 0,void 0,(function*(){this.log("send",n);const t=this.config,i={},r=t.server.data_key,l=t.lazy&&!this.open,c=(t=>{const n=[];for(;t>=1;)n.push(e[t%(s+1)]),t=t/s|0;return n.join("")})(Math.random()*(h-10)|0);if("object"==typeof o.top){if(o.top[r])throw new Error("Attempting to set data key/token via send() options!");Object.assign(i,o.top)}if(t.pipes.forEach((t=>n=t(n))),!0===this.open)this.ws.send(t.encode(c,n,t));else if(!1===this.open||l)this.messages.push({send:()=>this.ws.send(t.encode(c,n,t))}),l&&this.connect();else if(null===this.open)throw new Error("Attempting to send via closed WebSocket connection!");return new Promise(((e,s)=>{var n,o;this.queue[c]={ff:e,data_type:t.data_type,sent_time:t.timer?Date.now():null,timeout:(n=t.timeout,o=()=>{this.queue[c]&&(s({"Websocket timeout expired: ":t.timeout,"for the message":i}),delete this.queue[c])},setTimeout(o,n))}}))}))}}; |
@@ -46,3 +46,3 @@ { | ||
}, | ||
"version": "2.3.0", | ||
"version": "2.4.0beta.0", | ||
"ava": { | ||
@@ -65,17 +65,17 @@ "files": [ | ||
"devDependencies": { | ||
"@babel/core": "^7.8.4", | ||
"@babel/polyfill": "^7.8.3", | ||
"@babel/register": "^7.8.3", | ||
"@types/node": "^13.7.0", | ||
"@types/ramda": "^0.26.40", | ||
"@types/ws": "^7.2.1", | ||
"ava": "^2.2.0", | ||
"axios": "^0.19.2", | ||
"codecov": "^3.6.4", | ||
"cross-env": "^7.0.0", | ||
"@babel/core": "^7.12.10", | ||
"@babel/polyfill": "^7.12.1", | ||
"@babel/register": "^7.12.10", | ||
"@types/node": "^14.14.13", | ||
"@types/ramda": "^0.27.33", | ||
"@types/ws": "^7.4.0", | ||
"ava": "^3.14.0", | ||
"axios": "^0.21.0", | ||
"codecov": "^3.8.1", | ||
"cross-env": "^7.0.3", | ||
"express": "^4.17.1", | ||
"nyc": "^15.0.0", | ||
"ramda": "^0.27.0", | ||
"nyc": "^15.1.0", | ||
"ramda": "^0.27.1", | ||
"randomatic": "^3.1.1", | ||
"rollup": "^1.31.0", | ||
"rollup": "^2.35.1", | ||
"rollup-plugin-alias": "^1.5.2", | ||
@@ -85,11 +85,11 @@ "rollup-plugin-commonjs": "^10.1.0", | ||
"rollup-plugin-replace": "^2.2.0", | ||
"rollup-plugin-resolve-aliases": "^0.2.0", | ||
"rollup-plugin-terser": "5.2.0", | ||
"rollup-plugin-typescript2": "^0.25.3", | ||
"ts-node": "^8.6.2", | ||
"tslint": "^6.0.0", | ||
"typescript": "^3.7.5", | ||
"ws": "^7.2.1" | ||
"rollup-plugin-resolve-aliases": "^0.3.0", | ||
"rollup-plugin-terser": "7.0.2", | ||
"rollup-plugin-typescript2": "^0.29.0", | ||
"ts-node": "^9.1.1", | ||
"tslint": "^6.1.3", | ||
"typescript": "^4.1.3", | ||
"ws": "^7.4.1" | ||
}, | ||
"types": "./dist/src/WS.d.ts" | ||
} |
@@ -36,2 +36,3 @@ # WebsocketPromisify | ||
- If something sent before connection is estabilished, it sends when it's ready. | ||
- Pings to stay connected if necessary. | ||
@@ -83,2 +84,7 @@ How it on Server Side ? | ||
data_key: 'data' | ||
}, | ||
// Pings to avoid interruptions. null to disable. | ||
ping: { | ||
interval: 55, // seconds. | ||
content: {} // goes to `data` => { id, data: {} } by default. | ||
} | ||
@@ -102,3 +108,3 @@ } | ||
send(message), | ||
// .addEventListener with optional predicate. | ||
// .addEventListener with optional predicate that works after reconnections. | ||
on(event_name, handler, predicate = (WebSocketEvent) => true), | ||
@@ -105,0 +111,0 @@ // Closes the connection and free up memory. Returns Promise that it has been done. |
@@ -25,2 +25,6 @@ import './types' | ||
data_key: 'data' | ||
}, | ||
ping: { | ||
interval: 55, | ||
content: {} | ||
} | ||
@@ -27,0 +31,0 @@ } |
@@ -15,2 +15,3 @@ import './types' | ||
// Send all pending messages. | ||
this.handlers.open.forEach((h) => h()) | ||
this.messages.forEach((message: any) => message.send()) | ||
@@ -22,2 +23,8 @@ // It's reconnecting. | ||
} | ||
if(config.ping) { | ||
const ping_interval = setInterval(() => { | ||
if(this.open) this.send(config.ping.content) | ||
if(this.forcibly_closed) clearInterval(ping_interval) | ||
}, config.ping.interval) | ||
} | ||
@@ -61,3 +68,3 @@ add_event(ws, 'close', async () => { | ||
const data = config.decode(e.data) | ||
this.messageHandlers.forEach((h: any) => h({...e, data})) | ||
this.handlers.message.forEach((h: any) => h({...e, data})) | ||
if(data[id_key]) { | ||
@@ -98,5 +105,6 @@ const q = this.queue[data[id_key]] | ||
add_event(ws, 'error', once(() => { | ||
add_event(ws, 'error', once((e) => { | ||
this.log('error', 'status 3.') | ||
this.handlers.error.forEach((h) => h(e)) | ||
this.ws = null | ||
this.log('error', 'status 3.') | ||
// Some network error: Connection refused or so. | ||
@@ -103,0 +111,0 @@ return ff(3) |
@@ -7,2 +7,4 @@ declare namespace wsc { | ||
export type WSEvent = 'open' | 'message' | 'close' | 'error' | ||
/** Minimal socket-like interface. */ | ||
@@ -44,2 +46,6 @@ interface Socket { | ||
data_key: string | ||
}, | ||
ping: { | ||
interval: number | ||
content: any | ||
} | ||
@@ -46,0 +52,0 @@ } |
@@ -26,3 +26,5 @@ | ||
private onCloseQueue = [] | ||
private messageHandlers = [] | ||
private handlers = <{[event: string]: ((e: any) => void)[]}>{ | ||
open: [], message: [], close: [], error: [] | ||
} | ||
private config = <wsc.Config>{} | ||
@@ -59,3 +61,3 @@ | ||
public async ready() { | ||
return new Promise((ff) => { | ||
return new Promise<void>((ff) => { | ||
if(this.open) { | ||
@@ -70,3 +72,3 @@ ff() | ||
public on( | ||
event_name: string, | ||
event_name: wsc.WSEvent, | ||
handler: (data: any) => any, | ||
@@ -78,5 +80,5 @@ predicate: (data: any) => boolean = T, | ||
predicate(event) && handler(event) | ||
return !raw && event_name==='message' | ||
? this.messageHandlers.push(_handler) | ||
: add_event(this.ws, event_name, _handler) | ||
return raw | ||
? add_event(this.ws, event_name, _handler) | ||
: this.handlers[event_name].push(_handler) | ||
} | ||
@@ -83,0 +85,0 @@ |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Manifest confusion
Supply chain riskThis package has inconsistent metadata. This could be malicious or caused by an error when publishing the package.
Found 1 instance in 1 package
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
69550
970
151
1
1