diff --git a/.babelrc b/.babelrc deleted file mode 100644 index 3cdc69a..0000000 --- a/.babelrc +++ /dev/null @@ -1,8 +0,0 @@ -{ - "presets": [ - ["@babel/preset-env"] - ], - "plugins": [ - "@babel/plugin-transform-runtime" - ] -} diff --git a/.eslintignore b/.eslintignore new file mode 100644 index 0000000..7773828 --- /dev/null +++ b/.eslintignore @@ -0,0 +1 @@ +dist/ \ No newline at end of file diff --git a/API.md b/API.md index 76093fb..ba53f75 100644 --- a/API.md +++ b/API.md @@ -54,9 +54,19 @@ Departing from version 2.x, there's been some minor API changes. A breaking chan `client.login` now throws an error in case of failed login. Enclose the code using that method in a `try/catch` block to mitigate unhandled exceptions. -## Migrating to 8.x +## Migrating to 9.x -Starting with v8.0.0, the library switched to using ESNext (ESM). The consumers of this package version must ensure they use `import` instead of `require` to import resources from this package. +Starting with v9.0.0 this is a hybrid ES Modules / CommonJS library. + +Additionally, all of the exports formerly in the `lib/` directory are now bundled and exported from `rpc-websockets` itself. Any inner dependencies that you used to import can now be imported from the main package. + +```ts +// Before +import WebSocketFactory from "rpc-websockets/dist/lib/client/websocket.cjs"; + +// After +import { WebSocket as WebSocketFactory } from "rpc-websockets"; +``` ## Client diff --git a/build-browser-bundle.mjs b/build-browser-bundle.mjs deleted file mode 100755 index 18be4ca..0000000 --- a/build-browser-bundle.mjs +++ /dev/null @@ -1,15 +0,0 @@ -#!/usr/bin/env -S npx tsx -- - -import { build } from "esbuild" -import babelPlugin from "esbuild-plugin-babel" - -await build({ - entryPoints: ["./dist/index.browser.cjs"], - outfile: "./dist/index.browser-bundle.js", - bundle: true, - format: "iife", - globalName: "RPCWebsocket", - minify: true, - plugins: [babelPlugin()], - treeShaking: true, -}) diff --git a/dist/index.browser-bundle.js b/dist/index.browser-bundle.js index e1169c5..9bffe2d 100644 --- a/dist/index.browser-bundle.js +++ b/dist/index.browser-bundle.js @@ -1,6 +1,14 @@ -"use strict";var RPCWebsocket=(()=>{var et=Object.create;var je=Object.defineProperty;var tt=Object.getOwnPropertyDescriptor;var rt=Object.getOwnPropertyNames;var nt=Object.getPrototypeOf,ot=Object.prototype.hasOwnProperty;var O=(r,e)=>()=>(r&&(e=r(r=0)),e);var N=(r,e)=>()=>(e||r((e={exports:{}}).exports,e),e.exports);var it=(r,e,n,t)=>{if(e&&typeof e=="object"||typeof e=="function")for(let s of rt(e))!ot.call(r,s)&&s!==n&&je(r,s,{get:()=>e[s],enumerable:!(t=tt(e,s))||t.enumerable});return r};var ct=(r,e,n)=>(n=r!=null?et(nt(r)):{},it(e||!r||!r.__esModule?je(n,"default",{value:r,enumerable:!0}):n,r));function j(r){"@babel/helpers - typeof";return j=typeof Symbol=="function"&&typeof Symbol.iterator=="symbol"?function(e){return typeof e}:function(e){return e&&typeof Symbol=="function"&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},j(r)}var J=O(()=>{});function de(r,e){if(j(r)!="object"||!r)return r;var n=r[Symbol.toPrimitive];if(n!==void 0){var t=n.call(r,e||"default");if(j(t)!="object")return t;throw new TypeError("@@toPrimitive must return a primitive value.")}return(e==="string"?String:Number)(r)}var Le=O(()=>{J()});function H(r){var e=de(r,"string");return j(e)=="symbol"?e:e+""}var ve=O(()=>{J();Le()});function Se(r,e){for(var n=0;n{ve()});function R(r,e){if(!(r instanceof e))throw new TypeError("Cannot call a class as a function")}var U=O(()=>{});function ye(r){if(r===void 0)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return r}var Ce=O(()=>{});function F(r,e){if(e&&(j(e)==="object"||typeof e=="function"))return e;if(e!==void 0)throw new TypeError("Derived constructors may only return object or undefined");return ye(r)}var ne=O(()=>{J();Ce()});function L(r){return L=Object.setPrototypeOf?Object.getPrototypeOf.bind():function(n){return n.__proto__||Object.getPrototypeOf(n)},L(r)}var oe=O(()=>{});function V(r,e){return V=Object.setPrototypeOf?Object.setPrototypeOf.bind():function(t,s){return t.__proto__=s,t},V(r,e)}var Re=O(()=>{});function $(r,e){if(typeof e!="function"&&e!==null)throw new TypeError("Super expression must either be null or a function");r.prototype=Object.create(e&&e.prototype,{constructor:{value:r,writable:!0,configurable:!0}}),Object.defineProperty(r,"prototype",{writable:!1}),e&&V(r,e)}var ie=O(()=>{Re()});function g(r,e,n){return e=H(e),e in r?Object.defineProperty(r,e,{value:n,enumerable:!0,configurable:!0,writable:!0}):r[e]=n,r}var me=O(()=>{ve()});var ge=N((zt,_e)=>{"use strict";var at=Object.prototype.hasOwnProperty,k="~";function X(){}Object.create&&(X.prototype=Object.create(null),new X().__proto__||(k=!1));function ut(r,e,n){this.fn=r,this.context=e,this.once=n||!1}function qe(r,e,n,t,s){if(typeof n!="function")throw new TypeError("The listener must be a function");var o=new ut(n,t||r,s),a=k?k+e:e;return r._events[a]?r._events[a].fn?r._events[a]=[r._events[a],o]:r._events[a].push(o):(r._events[a]=o,r._eventsCount++),r}function ce(r,e){--r._eventsCount===0?r._events=new X:delete r._events[e]}function b(){this._events=new X,this._eventsCount=0}b.prototype.eventNames=function(){var e=[],n,t;if(this._eventsCount===0)return e;for(t in n=this._events)at.call(n,t)&&e.push(k?t.slice(1):t);return Object.getOwnPropertySymbols?e.concat(Object.getOwnPropertySymbols(n)):e};b.prototype.listeners=function(e){var n=k?k+e:e,t=this._events[n];if(!t)return[];if(t.fn)return[t.fn];for(var s=0,o=t.length,a=new Array(o);s{"use strict";U();Q();ne();oe();ie();me();function st(r,e,n){return e=L(e),F(r,Te()?Reflect.construct(e,n||[],L(r).constructor):e.apply(r,n))}function Te(){try{var r=!Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],function(){}))}catch{}return(Te=function(){return!!r})()}Object.defineProperty(be,"__esModule",{value:!0});var ft=ge(),lt=function(r){function e(n,t,s){var o;return R(this,e),o=st(this,e),g(o,"socket",void 0),o.socket=new window.WebSocket(n,s),o.socket.onopen=function(){return o.emit("open")},o.socket.onmessage=function(a){return o.emit("message",a.data)},o.socket.onerror=function(a){return o.emit("error",a)},o.socket.onclose=function(a){o.emit("close",a.code,a.reason)},o}return $(e,r),C(e,[{key:"send",value:function(t,s,o){var a=o||s;try{this.socket.send(t),a()}catch(l){a(l)}}},{key:"close",value:function(t,s){this.socket.close(t,s)}},{key:"addEventListener",value:function(t,s,o){this.socket.addEventListener(t,s,o)}}])}(ft.EventEmitter);function pt(r,e){return new lt(r,e)}be.default=pt});function Ie(r,e,n,t,s,o,a){try{var l=r[o](a),c=l.value}catch(v){n(v);return}l.done?e(c):Promise.resolve(c).then(t,s)}function K(r){return function(){var e=this,n=arguments;return new Promise(function(t,s){var o=r.apply(e,n);function a(c){Ie(o,t,s,a,l,"next",c)}function l(c){Ie(o,t,s,a,l,"throw",c)}a(void 0)})}}var Ne=O(()=>{});function we(r,e){if(r==null)return{};var n={},t=Object.keys(r),s,o;for(o=0;o=0)&&(n[s]=r[s]);return n}var De=O(()=>{});function ke(r,e){if(r==null)return{};var n=we(r,e),t,s;if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(r);for(s=0;s=0)&&Object.prototype.propertyIsEnumerable.call(r,t)&&(n[t]=r[t])}return n}var Ge=O(()=>{De()});var Ae=N((or,q)=>{function xe(r){"@babel/helpers - typeof";return q.exports=xe=typeof Symbol=="function"&&typeof Symbol.iterator=="symbol"?function(e){return typeof e}:function(e){return e&&typeof Symbol=="function"&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},q.exports.__esModule=!0,q.exports.default=q.exports,xe(r)}q.exports=xe,q.exports.__esModule=!0,q.exports.default=q.exports});var Be=N((ir,T)=>{var Fe=Ae().default;function $e(){"use strict";T.exports=$e=function(){return e},T.exports.__esModule=!0,T.exports.default=T.exports;var r,e={},n=Object.prototype,t=n.hasOwnProperty,s=Object.defineProperty||function(f,i,u){f[i]=u.value},o=typeof Symbol=="function"?Symbol:{},a=o.iterator||"@@iterator",l=o.asyncIterator||"@@asyncIterator",c=o.toStringTag||"@@toStringTag";function v(f,i,u){return Object.defineProperty(f,i,{value:u,enumerable:!0,configurable:!0,writable:!0}),f[i]}try{v({},"")}catch{v=function(u,p,d){return u[p]=d}}function m(f,i,u,p){var d=i&&i.prototype instanceof ue?i:ue,h=Object.create(d.prototype),_=new pe(p||[]);return s(h,"_invoke",{value:Xe(f,u,_)}),h}function y(f,i,u){try{return{type:"normal",arg:f.call(i,u)}}catch(p){return{type:"throw",arg:p}}}e.wrap=m;var E="suspendedStart",S="suspendedYield",Z="executing",B="completed",P={};function ue(){}function ee(){}function D(){}var se={};v(se,a,function(){return this});var fe=Object.getPrototypeOf,te=fe&&fe(fe(he([])));te&&te!==n&&t.call(te,a)&&(se=te);var W=D.prototype=ue.prototype=Object.create(se);function Pe(f){["next","throw","return"].forEach(function(i){v(f,i,function(u){return this._invoke(i,u)})})}function re(f,i){function u(d,h,_,w){var x=y(f[d],f,h);if(x.type!=="throw"){var G=x.arg,I=G.value;return I&&Fe(I)=="object"&&t.call(I,"__await")?i.resolve(I.__await).then(function(A){u("next",A,_,w)},function(A){u("throw",A,_,w)}):i.resolve(I).then(function(A){G.value=A,_(G)},function(A){return u("throw",A,_,w)})}w(x.arg)}var p;s(this,"_invoke",{value:function(h,_){function w(){return new i(function(x,G){u(h,_,x,G)})}return p=p?p.then(w,w):w()}})}function Xe(f,i,u){var p=E;return function(d,h){if(p===Z)throw Error("Generator is already running");if(p===B){if(d==="throw")throw h;return{value:r,done:!0}}for(u.method=d,u.arg=h;;){var _=u.delegate;if(_){var w=Ee(_,u);if(w){if(w===P)continue;return w}}if(u.method==="next")u.sent=u._sent=u.arg;else if(u.method==="throw"){if(p===E)throw p=B,u.arg;u.dispatchException(u.arg)}else u.method==="return"&&u.abrupt("return",u.arg);p=Z;var x=y(f,i,u);if(x.type==="normal"){if(p=u.done?B:S,x.arg===P)continue;return{value:x.arg,done:u.done}}x.type==="throw"&&(p=B,u.method="throw",u.arg=x.arg)}}}function Ee(f,i){var u=i.method,p=f.iterator[u];if(p===r)return i.delegate=null,u==="throw"&&f.iterator.return&&(i.method="return",i.arg=r,Ee(f,i),i.method==="throw")||u!=="return"&&(i.method="throw",i.arg=new TypeError("The iterator does not provide a '"+u+"' method")),P;var d=y(p,f.iterator,i.arg);if(d.type==="throw")return i.method="throw",i.arg=d.arg,i.delegate=null,P;var h=d.arg;return h?h.done?(i[f.resultName]=h.value,i.next=f.nextLoc,i.method!=="return"&&(i.method="next",i.arg=r),i.delegate=null,P):h:(i.method="throw",i.arg=new TypeError("iterator result is not an object"),i.delegate=null,P)}function Ze(f){var i={tryLoc:f[0]};1 in f&&(i.catchLoc=f[1]),2 in f&&(i.finallyLoc=f[2],i.afterLoc=f[3]),this.tryEntries.push(i)}function le(f){var i=f.completion||{};i.type="normal",delete i.arg,f.completion=i}function pe(f){this.tryEntries=[{tryLoc:"root"}],f.forEach(Ze,this),this.reset(!0)}function he(f){if(f||f===""){var i=f[a];if(i)return i.call(f);if(typeof f.next=="function")return f;if(!isNaN(f.length)){var u=-1,p=function d(){for(;++u=0;--d){var h=this.tryEntries[d],_=h.completion;if(h.tryLoc==="root")return p("end");if(h.tryLoc<=this.prev){var w=t.call(h,"catchLoc"),x=t.call(h,"finallyLoc");if(w&&x){if(this.prev=0;--p){var d=this.tryEntries[p];if(d.tryLoc<=this.prev&&t.call(d,"finallyLoc")&&this.prev=0;--u){var p=this.tryEntries[u];if(p.finallyLoc===i)return this.complete(p.completion,p.afterLoc),le(p),P}},catch:function(i){for(var u=this.tryEntries.length-1;u>=0;--u){var p=this.tryEntries[u];if(p.tryLoc===i){var d=p.completion;if(d.type==="throw"){var h=d.arg;le(p)}return h}}throw Error("illegal catch attempt")},delegateYield:function(i,u,p){return this.delegate={iterator:he(i),resultName:u,nextLoc:p},this.method==="next"&&(this.arg=r),P}},e}T.exports=$e,T.exports.__esModule=!0,T.exports.default=T.exports});var Ke=N((cr,We)=>{var ae=Be()();We.exports=ae;try{regeneratorRuntime=ae}catch{typeof globalThis=="object"?globalThis.regeneratorRuntime=ae:Function("r","regeneratorRuntime = r")(ae)}});var Ye=N(Y=>{"use strict";U();Q();Object.defineProperty(Y,"__esModule",{value:!0});Y.createError=Y.DefaultDataPack=void 0;var ht=new Map([[-32e3,"Event not provided"],[-32600,"Invalid Request"],[-32601,"Method not found"],[-32602,"Invalid params"],[-32603,"Internal error"],[-32604,"Params not found"],[-32605,"Method forbidden"],[-32606,"Event forbidden"],[-32700,"Parse error"]]),dt=function(){function r(){R(this,r)}return C(r,[{key:"encode",value:function(n){return JSON.stringify(n)}},{key:"decode",value:function(n){return JSON.parse(n)}}])}();Y.DefaultDataPack=dt;function vt(r,e){var n={code:r,message:ht.get(r)||"Internal Server Error"};return e&&(n.data=e),n}Y.createError=vt});var Qe=N(Oe=>{"use strict";Ne();J();Ge();U();Q();ne();oe();ie();me();var M=ct(Ke()),yt=["autoconnect","reconnect","reconnect_interval","max_reconnects"];function ze(r,e){var n=Object.keys(r);if(Object.getOwnPropertySymbols){var t=Object.getOwnPropertySymbols(r);e&&(t=t.filter(function(s){return Object.getOwnPropertyDescriptor(r,s).enumerable})),n.push.apply(n,t)}return n}function Je(r){for(var e=1;e1&&arguments[1]!==void 0?arguments[1]:"ws://localhost:8080",o=arguments.length>2&&arguments[2]!==void 0?arguments[2]:{},a=o.autoconnect,l=a===void 0?!0:a,c=o.reconnect,v=c===void 0?!0:c,m=o.reconnect_interval,y=m===void 0?1e3:m,E=o.max_reconnects,S=E===void 0?5:E,Z=ke(o,yt),B=arguments.length>3?arguments[3]:void 0,P=arguments.length>4?arguments[4]:void 0;return R(this,e),t=mt(this,e),g(t,"address",void 0),g(t,"rpc_id",void 0),g(t,"queue",void 0),g(t,"options",void 0),g(t,"autoconnect",void 0),g(t,"ready",void 0),g(t,"reconnect",void 0),g(t,"reconnect_timer_id",void 0),g(t,"reconnect_interval",void 0),g(t,"max_reconnects",void 0),g(t,"rest_options",void 0),g(t,"current_reconnects",void 0),g(t,"generate_request_id",void 0),g(t,"socket",void 0),g(t,"webSocketFactory",void 0),g(t,"dataPack",void 0),t.webSocketFactory=n,t.queue={},t.rpc_id=0,t.address=s,t.autoconnect=l,t.ready=!1,t.reconnect=v,t.reconnect_timer_id=void 0,t.reconnect_interval=y,t.max_reconnects=S,t.rest_options=Z,t.current_reconnects=0,t.generate_request_id=B||function(){return++t.rpc_id},P?t.dataPack=P:t.dataPack=new gt.DefaultDataPack,t.autoconnect&&t._connect(t.address,Je({autoconnect:t.autoconnect,reconnect:t.reconnect,reconnect_interval:t.reconnect_interval,max_reconnects:t.max_reconnects},t.rest_options)),t}return $(e,r),C(e,[{key:"connect",value:function(){this.socket||this._connect(this.address,Je({autoconnect:this.autoconnect,reconnect:this.reconnect,reconnect_interval:this.reconnect_interval,max_reconnects:this.max_reconnects},this.rest_options))}},{key:"call",value:function(t,s,o,a){var l=this;return!a&&j(o)==="object"&&(a=o,o=null),new Promise(function(c,v){if(!l.ready)return v(new Error("socket not ready"));var m=l.generate_request_id(t,s),y={jsonrpc:"2.0",method:t,params:s||void 0,id:m};l.socket.send(l.dataPack.encode(y),a,function(E){if(E)return v(E);l.queue[m]={promise:[c,v]},o&&(l.queue[m].timeout=setTimeout(function(){delete l.queue[m],v(new Error("reply timeout"))},o))})})}},{key:"login",value:function(){var n=K(M.default.mark(function s(o){var a;return M.default.wrap(function(c){for(;;)switch(c.prev=c.next){case 0:return c.next=2,this.call("rpc.login",o);case 2:if(a=c.sent,a){c.next=5;break}throw new Error("authentication failed");case 5:return c.abrupt("return",a);case 6:case"end":return c.stop()}},s,this)}));function t(s){return n.apply(this,arguments)}return t}()},{key:"listMethods",value:function(){var n=K(M.default.mark(function s(){return M.default.wrap(function(a){for(;;)switch(a.prev=a.next){case 0:return a.next=2,this.call("__listMethods");case 2:return a.abrupt("return",a.sent);case 3:case"end":return a.stop()}},s,this)}));function t(){return n.apply(this,arguments)}return t}()},{key:"notify",value:function(t,s){var o=this;return new Promise(function(a,l){if(!o.ready)return l(new Error("socket not ready"));var c={jsonrpc:"2.0",method:t,params:s};o.socket.send(o.dataPack.encode(c),function(v){if(v)return l(v);a()})})}},{key:"subscribe",value:function(){var n=K(M.default.mark(function s(o){var a;return M.default.wrap(function(c){for(;;)switch(c.prev=c.next){case 0:return typeof o=="string"&&(o=[o]),c.next=3,this.call("rpc.on",o);case 3:if(a=c.sent,!(typeof o=="string"&&a[o]!=="ok")){c.next=6;break}throw new Error("Failed subscribing to an event '"+o+"' with: "+a[o]);case 6:return c.abrupt("return",a);case 7:case"end":return c.stop()}},s,this)}));function t(s){return n.apply(this,arguments)}return t}()},{key:"unsubscribe",value:function(){var n=K(M.default.mark(function s(o){var a;return M.default.wrap(function(c){for(;;)switch(c.prev=c.next){case 0:return typeof o=="string"&&(o=[o]),c.next=3,this.call("rpc.off",o);case 3:if(a=c.sent,!(typeof o=="string"&&a[o]!=="ok")){c.next=6;break}throw new Error("Failed unsubscribing from an event with: "+a);case 6:return c.abrupt("return",a);case 7:case"end":return c.stop()}},s,this)}));function t(s){return n.apply(this,arguments)}return t}()},{key:"close",value:function(t,s){this.socket.close(t||1e3,s)}},{key:"setAutoReconnect",value:function(t){this.reconnect=t}},{key:"setReconnectInterval",value:function(t){this.reconnect_interval=t}},{key:"setMaxReconnects",value:function(t){this.max_reconnects=t}},{key:"_connect",value:function(t,s){var o=this;clearTimeout(this.reconnect_timer_id),this.socket=this.webSocketFactory(t,s),this.socket.addEventListener("open",function(){o.ready=!0,o.emit("open"),o.current_reconnects=0}),this.socket.addEventListener("message",function(a){var l=a.data;l instanceof ArrayBuffer&&(l=Buffer.from(l).toString());try{l=o.dataPack.decode(l)}catch{return}if(l.notification&&o.listeners(l.notification).length){if(!Object.keys(l.params).length)return o.emit(l.notification);var c=[l.notification];if(l.params.constructor===Object)c.push(l.params);else for(var v=0;vo.current_reconnects||o.max_reconnects===0)&&(o.reconnect_timer_id=setTimeout(function(){return o._connect(t,s)},o.reconnect_interval)))})}}])}(_t.EventEmitter);Oe.default=bt});var Pt=N(z=>{Q();U();ne();oe();ie();function wt(r,e,n){return e=L(e),F(r,Ue()?Reflect.construct(e,n||[],L(r).constructor):e.apply(r,n))}function Ue(){try{var r=!Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],function(){}))}catch{}return(Ue=function(){return!!r})()}var Ve=z&&z.__importDefault||function(r){return r&&r.__esModule?r:{default:r}};Object.defineProperty(z,"__esModule",{value:!0});z.Client=void 0;var kt=Ve(Me()),xt=Ve(Qe()),Ot=function(r){function e(){var n=arguments.length>0&&arguments[0]!==void 0?arguments[0]:"ws://localhost:8080",t=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{},s=t.autoconnect,o=s===void 0?!0:s,a=t.reconnect,l=a===void 0?!0:a,c=t.reconnect_interval,v=c===void 0?1e3:c,m=t.max_reconnects,y=m===void 0?5:m,E=arguments.length>2?arguments[2]:void 0;return R(this,e),wt(this,e,[kt.default,n,{autoconnect:o,reconnect:l,reconnect_interval:v,max_reconnects:y},E])}return $(e,r),C(e)}(xt.default);z.Client=Ot});return Pt();})(); -/*! Bundled license information: +var RPCWebsocket = (function (exports) { + 'use strict'; -@babel/runtime/helpers/regeneratorRuntime.js: - (*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/facebook/regenerator/blob/main/LICENSE *) -*/ + var Rr=Object.create;var at=Object.defineProperty;var Pr=Object.getOwnPropertyDescriptor;var Lr=Object.getOwnPropertyNames,ct=Object.getOwnPropertySymbols,Nr=Object.getPrototypeOf,It=Object.prototype.hasOwnProperty,qt=Object.prototype.propertyIsEnumerable;var Bt=(h,u,c)=>u in h?at(h,u,{enumerable:!0,configurable:!0,writable:!0,value:c}):h[u]=c,_t=(h,u)=>{for(var c in u||(u={}))It.call(u,c)&&Bt(h,c,u[c]);if(ct)for(var c of ct(u))qt.call(u,c)&&Bt(h,c,u[c]);return h};var Dt=(h,u)=>{var c={};for(var l in h)It.call(h,l)&&u.indexOf(l)<0&&(c[l]=h[l]);if(h!=null&&ct)for(var l of ct(h))u.indexOf(l)<0&&qt.call(h,l)&&(c[l]=h[l]);return c};var it=(h,u)=>()=>(h&&(u=h(h=0)),u);var Wr=(h,u)=>()=>(u||h((u={exports:{}}).exports,u),u.exports),Mr=(h,u)=>{for(var c in u)at(h,c,{get:u[c],enumerable:!0});},Or=(h,u,c,l)=>{if(u&&typeof u=="object"||typeof u=="function")for(let p of Lr(u))!It.call(h,p)&&p!==c&&at(h,p,{get:()=>u[p],enumerable:!(l=Pr(u,p))||l.enumerable});return h};var jt=(h,u,c)=>(c=h!=null?Rr(Nr(h)):{},Or(!h||!h.__esModule?at(c,"default",{value:h,enumerable:!0}):c,h));var U=(h,u,c)=>Bt(h,typeof u!="symbol"?u+"":u,c);var T=it(()=>{});var j={};Mr(j,{_debugEnd:()=>Ce,_debugProcess:()=>Te,_events:()=>Ke,_eventsCount:()=>Xe,_exiting:()=>pe,_fatalExceptions:()=>xe,_getActiveHandles:()=>ye,_getActiveRequests:()=>de,_kill:()=>we,_linkedBinding:()=>ae,_maxListeners:()=>He,_preload_modules:()=>je,_rawDebug:()=>ue,_startProfilerIdleNotifier:()=>Re,_stopProfilerIdleNotifier:()=>Pe,_tickCallback:()=>Ue,abort:()=>Me,addListener:()=>Je,allowedNodeEnvironmentFlags:()=>be,arch:()=>Xt,argv:()=>Vt,argv0:()=>De,assert:()=>Ae,binding:()=>re,chdir:()=>oe,config:()=>le,cpuUsage:()=>lt,cwd:()=>ie,debugPort:()=>qe,default:()=>ir,dlopen:()=>fe,domain:()=>he,emit:()=>tr,emitWarning:()=>ee,env:()=>Qt,execArgv:()=>zt,execPath:()=>Fe,exit:()=>Ie,features:()=>ke,hasUncaughtExceptionCaptureCallback:()=>Se,hrtime:()=>pt,kill:()=>Be,listeners:()=>nr,memoryUsage:()=>Ee,moduleLoadList:()=>ce,nextTick:()=>Gt,off:()=>Ve,on:()=>K,once:()=>Qe,openStdin:()=>_e,pid:()=>Oe,platform:()=>Jt,ppid:()=>$e,prependListener:()=>er,prependOnceListener:()=>rr,reallyExit:()=>me,release:()=>se,removeAllListeners:()=>Ze,removeListener:()=>ze,resourceUsage:()=>ge,setSourceMapsEnabled:()=>Ye,setUncaughtExceptionCaptureCallback:()=>ve,stderr:()=>Ne,stdin:()=>We,stdout:()=>Le,title:()=>Kt,umask:()=>ne,uptime:()=>Ge,version:()=>Zt,versions:()=>te});function kt(h){throw new Error("Node.js process "+h+" is not supported by JSPM core outside of Node.js")}function $r(){!rt||!V||(rt=!1,V.length?H=V.concat(H):ht=-1,H.length&&Yt());}function Yt(){if(!rt){var h=setTimeout($r,0);rt=!0;for(var u=H.length;u;){for(V=H,H=[];++ht1)for(var c=1;c{T();R();C();H=[],rt=!1,ht=-1;Ht.prototype.run=function(){this.fun.apply(null,this.array);};Kt="browser",Xt="x64",Jt="browser",Qt={PATH:"/usr/bin",LANG:navigator.language+".UTF-8",PWD:"/",HOME:"/home",TMP:"/tmp"},Vt=["/usr/bin/node"],zt=[],Zt="v16.8.0",te={},ee=function(h,u){console.warn((u?u+": ":"")+h);},re=function(h){kt("binding");},ne=function(h){return 0},ie=function(){return "/"},oe=function(h){},se={name:"node",sourceUrl:"",headersUrl:"",libUrl:""};ue=N,ce=[];he={},pe=!1,le={};me=N,we=N,lt=function(){return {}},ge=lt,Ee=lt,Be=N,Ie=N,_e=N,be={};ke={inspector:!1,debug:!1,uv:!1,ipv6:!1,tls_alpn:!1,tls_sni:!1,tls_ocsp:!1,tls:!1,cached_builtins:!0},xe=N,ve=N;Ue=N,Te=N,Ce=N,Re=N,Pe=N,Le=void 0,Ne=void 0,We=void 0,Me=N,Oe=2,$e=1,Fe="/bin/usr/node",qe=9229,De="node",je=[],Ye=N,J={now:typeof performance!="undefined"?performance.now.bind(performance):void 0,timing:typeof performance!="undefined"?performance.timing:void 0};J.now===void 0&&(bt=Date.now(),J.timing&&J.timing.navigationStart&&(bt=J.timing.navigationStart),J.now=()=>Date.now()-bt);At=1e9;pt.bigint=function(h){var u=pt(h);return typeof BigInt=="undefined"?u[0]*At+u[1]:BigInt(u[0]*At)+BigInt(u[1])};He=10,Ke={},Xe=0;Je=K,Qe=K,Ve=K,ze=K,Ze=K,tr=N,er=K,rr=K;ir={version:Zt,versions:te,arch:Xt,platform:Jt,release:se,_rawDebug:ue,moduleLoadList:ce,binding:re,_linkedBinding:ae,_events:Ke,_eventsCount:Xe,_maxListeners:He,on:K,addListener:Je,once:Qe,off:Ve,removeListener:ze,removeAllListeners:Ze,emit:tr,prependListener:er,prependOnceListener:rr,listeners:nr,domain:he,_exiting:pe,config:le,dlopen:fe,uptime:Ge,_getActiveRequests:de,_getActiveHandles:ye,reallyExit:me,_kill:we,cpuUsage:lt,resourceUsage:ge,memoryUsage:Ee,kill:Be,exit:Ie,openStdin:_e,allowedNodeEnvironmentFlags:be,assert:Ae,features:ke,_fatalExceptions:xe,setUncaughtExceptionCaptureCallback:ve,hasUncaughtExceptionCaptureCallback:Se,emitWarning:ee,nextTick:Gt,_tickCallback:Ue,_debugProcess:Te,_debugEnd:Ce,_startProfilerIdleNotifier:Re,_stopProfilerIdleNotifier:Pe,stdout:Le,stdin:We,stderr:Ne,abort:Me,umask:ne,chdir:oe,cwd:ie,env:Qt,title:Kt,argv:Vt,execArgv:zt,pid:Oe,ppid:$e,execPath:Fe,debugPort:qe,hrtime:pt,argv0:De,_preload_modules:je,setSourceMapsEnabled:Ye};});var C=it(()=>{or();});function Fr(){if(sr)return ot;sr=!0,ot.byteLength=E,ot.toByteArray=b,ot.fromByteArray=L;for(var h=[],u=[],c=typeof Uint8Array!="undefined"?Uint8Array:Array,l="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",p=0,f=l.length;p0)throw new Error("Invalid string. Length must be a multiple of 4");var _=y.indexOf("=");_===-1&&(_=g);var S=_===g?0:4-_%4;return [_,S]}function E(y){var g=i(y),_=g[0],S=g[1];return (_+S)*3/4-S}function d(y,g,_){return (g+_)*3/4-_}function b(y){var g,_=i(y),S=_[0],$=_[1],v=new c(d(y,S,$)),F=0,D=$>0?S-4:S,M;for(M=0;M>16&255,v[F++]=g>>8&255,v[F++]=g&255;return $===2&&(g=u[y.charCodeAt(M)]<<2|u[y.charCodeAt(M+1)]>>4,v[F++]=g&255),$===1&&(g=u[y.charCodeAt(M)]<<10|u[y.charCodeAt(M+1)]<<4|u[y.charCodeAt(M+2)]>>2,v[F++]=g>>8&255,v[F++]=g&255),v}function B(y){return h[y>>18&63]+h[y>>12&63]+h[y>>6&63]+h[y&63]}function m(y,g,_){for(var S,$=[],v=g;v<_;v+=3)S=(y[v]<<16&16711680)+(y[v+1]<<8&65280)+(y[v+2]&255),$.push(B(S));return $.join("")}function L(y){for(var g,_=y.length,S=_%3,$=[],v=16383,F=0,D=_-S;FD?D:F+v));return S===1?(g=y[_-1],$.push(h[g>>2]+h[g<<4&63]+"==")):S===2&&(g=(y[_-2]<<8)+y[_-1],$.push(h[g>>10]+h[g>>4&63]+h[g<<2&63]+"=")),$.join("")}return ot}function qr(){if(ur)return ft;ur=!0;return ft.read=function(h,u,c,l,p){var f,i,E=p*8-l-1,d=(1<>1,B=-7,m=c?p-1:0,L=c?-1:1,y=h[u+m];for(m+=L,f=y&(1<<-B)-1,y>>=-B,B+=E;B>0;f=f*256+h[u+m],m+=L,B-=8);for(i=f&(1<<-B)-1,f>>=-B,B+=l;B>0;i=i*256+h[u+m],m+=L,B-=8);if(f===0)f=1-b;else {if(f===d)return i?NaN:(y?-1:1)*(1/0);i=i+Math.pow(2,l),f=f-b;}return (y?-1:1)*i*Math.pow(2,f-l)},ft.write=function(h,u,c,l,p,f){var i,E,d,b=f*8-p-1,B=(1<>1,L=p===23?Math.pow(2,-24)-Math.pow(2,-77):0,y=l?0:f-1,g=l?1:-1,_=u<0||u===0&&1/u<0?1:0;for(u=Math.abs(u),isNaN(u)||u===1/0?(E=isNaN(u)?1:0,i=B):(i=Math.floor(Math.log(u)/Math.LN2),u*(d=Math.pow(2,-i))<1&&(i--,d*=2),i+m>=1?u+=L/d:u+=L*Math.pow(2,1-m),u*d>=2&&(i++,d/=2),i+m>=B?(E=0,i=B):i+m>=1?(E=(u*d-1)*Math.pow(2,p),i=i+m):(E=u*Math.pow(2,m-1)*Math.pow(2,p),i=0));p>=8;h[c+y]=E&255,y+=g,E/=256,p-=8);for(i=i<0;h[c+y]=i&255,y+=g,i/=256,b-=8);h[c+y-g]|=_*128;},ft}function Dr(){if(cr)return z;cr=!0;let h=Fr(),u=qr(),c=typeof Symbol=="function"&&typeof Symbol.for=="function"?Symbol.for("nodejs.util.inspect.custom"):null;z.Buffer=i,z.SlowBuffer=$,z.INSPECT_MAX_BYTES=50;let l=2147483647;z.kMaxLength=l,i.TYPED_ARRAY_SUPPORT=p(),!i.TYPED_ARRAY_SUPPORT&&typeof console!="undefined"&&typeof console.error=="function"&&console.error("This browser lacks typed array (Uint8Array) support which is required by `buffer` v5.x. Use `buffer` v4.x if you require old browser support.");function p(){try{let r=new Uint8Array(1),t={foo:function(){return 42}};return Object.setPrototypeOf(t,Uint8Array.prototype),Object.setPrototypeOf(r,t),r.foo()===42}catch(r){return !1}}Object.defineProperty(i.prototype,"parent",{enumerable:!0,get:function(){if(i.isBuffer(this))return this.buffer}}),Object.defineProperty(i.prototype,"offset",{enumerable:!0,get:function(){if(i.isBuffer(this))return this.byteOffset}});function f(r){if(r>l)throw new RangeError('The value "'+r+'" is invalid for option "size"');let t=new Uint8Array(r);return Object.setPrototypeOf(t,i.prototype),t}function i(r,t,e){if(typeof r=="number"){if(typeof t=="string")throw new TypeError('The "string" argument must be of type string. Received type number');return B(r)}return E(r,t,e)}i.poolSize=8192;function E(r,t,e){if(typeof r=="string")return m(r,t);if(ArrayBuffer.isView(r))return y(r);if(r==null)throw new TypeError("The first argument must be one of type string, Buffer, ArrayBuffer, Array, or Array-like Object. Received type "+typeof r);if(Y(r,ArrayBuffer)||r&&Y(r.buffer,ArrayBuffer)||typeof SharedArrayBuffer!="undefined"&&(Y(r,SharedArrayBuffer)||r&&Y(r.buffer,SharedArrayBuffer)))return g(r,t,e);if(typeof r=="number")throw new TypeError('The "value" argument must not be of type number. Received type number');let n=r.valueOf&&r.valueOf();if(n!=null&&n!==r)return i.from(n,t,e);let o=_(r);if(o)return o;if(typeof Symbol!="undefined"&&Symbol.toPrimitive!=null&&typeof r[Symbol.toPrimitive]=="function")return i.from(r[Symbol.toPrimitive]("string"),t,e);throw new TypeError("The first argument must be one of type string, Buffer, ArrayBuffer, Array, or Array-like Object. Received type "+typeof r)}i.from=function(r,t,e){return E(r,t,e)},Object.setPrototypeOf(i.prototype,Uint8Array.prototype),Object.setPrototypeOf(i,Uint8Array);function d(r){if(typeof r!="number")throw new TypeError('"size" argument must be of type number');if(r<0)throw new RangeError('The value "'+r+'" is invalid for option "size"')}function b(r,t,e){return d(r),r<=0?f(r):t!==void 0?typeof e=="string"?f(r).fill(t,e):f(r).fill(t):f(r)}i.alloc=function(r,t,e){return b(r,t,e)};function B(r){return d(r),f(r<0?0:S(r)|0)}i.allocUnsafe=function(r){return B(r)},i.allocUnsafeSlow=function(r){return B(r)};function m(r,t){if((typeof t!="string"||t==="")&&(t="utf8"),!i.isEncoding(t))throw new TypeError("Unknown encoding: "+t);let e=v(r,t)|0,n=f(e),o=n.write(r,t);return o!==e&&(n=n.slice(0,o)),n}function L(r){let t=r.length<0?0:S(r.length)|0,e=f(t);for(let n=0;n=l)throw new RangeError("Attempt to allocate Buffer larger than maximum size: 0x"+l.toString(16)+" bytes");return r|0}function $(r){return +r!=r&&(r=0),i.alloc(+r)}i.isBuffer=function(t){return t!=null&&t._isBuffer===!0&&t!==i.prototype},i.compare=function(t,e){if(Y(t,Uint8Array)&&(t=i.from(t,t.offset,t.byteLength)),Y(e,Uint8Array)&&(e=i.from(e,e.offset,e.byteLength)),!i.isBuffer(t)||!i.isBuffer(e))throw new TypeError('The "buf1", "buf2" arguments must be one of type Buffer or Uint8Array');if(t===e)return 0;let n=t.length,o=e.length;for(let s=0,a=Math.min(n,o);so.length?(i.isBuffer(a)||(a=i.from(a)),a.copy(o,s)):Uint8Array.prototype.set.call(o,a,s);else if(i.isBuffer(a))a.copy(o,s);else throw new TypeError('"list" argument must be an Array of Buffers');s+=a.length;}return o};function v(r,t){if(i.isBuffer(r))return r.length;if(ArrayBuffer.isView(r)||Y(r,ArrayBuffer))return r.byteLength;if(typeof r!="string")throw new TypeError('The "string" argument must be one of type string, Buffer, or ArrayBuffer. Received type '+typeof r);let e=r.length,n=arguments.length>2&&arguments[2]===!0;if(!n&&e===0)return 0;let o=!1;for(;;)switch(t){case"ascii":case"latin1":case"binary":return e;case"utf8":case"utf-8":return gt(r).length;case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return e*2;case"hex":return e>>>1;case"base64":return Ft(r).length;default:if(o)return n?-1:gt(r).length;t=(""+t).toLowerCase(),o=!0;}}i.byteLength=v;function F(r,t,e){let n=!1;if((t===void 0||t<0)&&(t=0),t>this.length||((e===void 0||e>this.length)&&(e=this.length),e<=0)||(e>>>=0,t>>>=0,e<=t))return "";for(r||(r="utf8");;)switch(r){case"hex":return br(this,t,e);case"utf8":case"utf-8":return Ct(this,t,e);case"ascii":return Ir(this,t,e);case"latin1":case"binary":return _r(this,t,e);case"base64":return Er(this,t,e);case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return Ar(this,t,e);default:if(n)throw new TypeError("Unknown encoding: "+r);r=(r+"").toLowerCase(),n=!0;}}i.prototype._isBuffer=!0;function D(r,t,e){let n=r[t];r[t]=r[e],r[e]=n;}i.prototype.swap16=function(){let t=this.length;if(t%2!==0)throw new RangeError("Buffer size must be a multiple of 16-bits");for(let e=0;ee&&(t+=" ... "),""},c&&(i.prototype[c]=i.prototype.inspect),i.prototype.compare=function(t,e,n,o,s){if(Y(t,Uint8Array)&&(t=i.from(t,t.offset,t.byteLength)),!i.isBuffer(t))throw new TypeError('The "target" argument must be one of type Buffer or Uint8Array. Received type '+typeof t);if(e===void 0&&(e=0),n===void 0&&(n=t?t.length:0),o===void 0&&(o=0),s===void 0&&(s=this.length),e<0||n>t.length||o<0||s>this.length)throw new RangeError("out of range index");if(o>=s&&e>=n)return 0;if(o>=s)return -1;if(e>=n)return 1;if(e>>>=0,n>>>=0,o>>>=0,s>>>=0,this===t)return 0;let a=s-o,w=n-e,k=Math.min(a,w),A=this.slice(o,s),x=t.slice(e,n);for(let I=0;I2147483647?e=2147483647:e<-2147483648&&(e=-2147483648),e=+e,Et(e)&&(e=o?0:r.length-1),e<0&&(e=r.length+e),e>=r.length){if(o)return -1;e=r.length-1;}else if(e<0)if(o)e=0;else return -1;if(typeof t=="string"&&(t=i.from(t,n)),i.isBuffer(t))return t.length===0?-1:Tt(r,t,e,n,o);if(typeof t=="number")return t=t&255,typeof Uint8Array.prototype.indexOf=="function"?o?Uint8Array.prototype.indexOf.call(r,t,e):Uint8Array.prototype.lastIndexOf.call(r,t,e):Tt(r,[t],e,n,o);throw new TypeError("val must be string, number or Buffer")}function Tt(r,t,e,n,o){let s=1,a=r.length,w=t.length;if(n!==void 0&&(n=String(n).toLowerCase(),n==="ucs2"||n==="ucs-2"||n==="utf16le"||n==="utf-16le")){if(r.length<2||t.length<2)return -1;s=2,a/=2,w/=2,e/=2;}function k(x,I){return s===1?x[I]:x.readUInt16BE(I*s)}let A;if(o){let x=-1;for(A=e;Aa&&(e=a-w),A=e;A>=0;A--){let x=!0;for(let I=0;Io&&(n=o)):n=o;let s=t.length;n>s/2&&(n=s/2);let a;for(a=0;a>>0,isFinite(n)?(n=n>>>0,o===void 0&&(o="utf8")):(o=n,n=void 0);else throw new Error("Buffer.write(string, encoding, offset[, length]) is no longer supported");let s=this.length-e;if((n===void 0||n>s)&&(n=s),t.length>0&&(n<0||e<0)||e>this.length)throw new RangeError("Attempt to write outside buffer bounds");o||(o="utf8");let a=!1;for(;;)switch(o){case"hex":return dr(this,t,e,n);case"utf8":case"utf-8":return yr(this,t,e,n);case"ascii":case"latin1":case"binary":return mr(this,t,e,n);case"base64":return wr(this,t,e,n);case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return gr(this,t,e,n);default:if(a)throw new TypeError("Unknown encoding: "+o);o=(""+o).toLowerCase(),a=!0;}},i.prototype.toJSON=function(){return {type:"Buffer",data:Array.prototype.slice.call(this._arr||this,0)}};function Er(r,t,e){return t===0&&e===r.length?h.fromByteArray(r):h.fromByteArray(r.slice(t,e))}function Ct(r,t,e){e=Math.min(r.length,e);let n=[],o=t;for(;o239?4:s>223?3:s>191?2:1;if(o+w<=e){let k,A,x,I;switch(w){case 1:s<128&&(a=s);break;case 2:k=r[o+1],(k&192)===128&&(I=(s&31)<<6|k&63,I>127&&(a=I));break;case 3:k=r[o+1],A=r[o+2],(k&192)===128&&(A&192)===128&&(I=(s&15)<<12|(k&63)<<6|A&63,I>2047&&(I<55296||I>57343)&&(a=I));break;case 4:k=r[o+1],A=r[o+2],x=r[o+3],(k&192)===128&&(A&192)===128&&(x&192)===128&&(I=(s&15)<<18|(k&63)<<12|(A&63)<<6|x&63,I>65535&&I<1114112&&(a=I));}}a===null?(a=65533,w=1):a>65535&&(a-=65536,n.push(a>>>10&1023|55296),a=56320|a&1023),n.push(a),o+=w;}return Br(n)}let Rt=4096;function Br(r){let t=r.length;if(t<=Rt)return String.fromCharCode.apply(String,r);let e="",n=0;for(;nn)&&(e=n);let o="";for(let s=t;sn&&(t=n),e<0?(e+=n,e<0&&(e=0)):e>n&&(e=n),ee)throw new RangeError("Trying to access beyond buffer length")}i.prototype.readUintLE=i.prototype.readUIntLE=function(t,e,n){t=t>>>0,e=e>>>0,n||P(t,e,this.length);let o=this[t],s=1,a=0;for(;++a>>0,e=e>>>0,n||P(t,e,this.length);let o=this[t+--e],s=1;for(;e>0&&(s*=256);)o+=this[t+--e]*s;return o},i.prototype.readUint8=i.prototype.readUInt8=function(t,e){return t=t>>>0,e||P(t,1,this.length),this[t]},i.prototype.readUint16LE=i.prototype.readUInt16LE=function(t,e){return t=t>>>0,e||P(t,2,this.length),this[t]|this[t+1]<<8},i.prototype.readUint16BE=i.prototype.readUInt16BE=function(t,e){return t=t>>>0,e||P(t,2,this.length),this[t]<<8|this[t+1]},i.prototype.readUint32LE=i.prototype.readUInt32LE=function(t,e){return t=t>>>0,e||P(t,4,this.length),(this[t]|this[t+1]<<8|this[t+2]<<16)+this[t+3]*16777216},i.prototype.readUint32BE=i.prototype.readUInt32BE=function(t,e){return t=t>>>0,e||P(t,4,this.length),this[t]*16777216+(this[t+1]<<16|this[t+2]<<8|this[t+3])},i.prototype.readBigUInt64LE=X(function(t){t=t>>>0,et(t,"offset");let e=this[t],n=this[t+7];(e===void 0||n===void 0)&&nt(t,this.length-8);let o=e+this[++t]*2**8+this[++t]*2**16+this[++t]*2**24,s=this[++t]+this[++t]*2**8+this[++t]*2**16+n*2**24;return BigInt(o)+(BigInt(s)<>>0,et(t,"offset");let e=this[t],n=this[t+7];(e===void 0||n===void 0)&&nt(t,this.length-8);let o=e*2**24+this[++t]*2**16+this[++t]*2**8+this[++t],s=this[++t]*2**24+this[++t]*2**16+this[++t]*2**8+n;return (BigInt(o)<>>0,e=e>>>0,n||P(t,e,this.length);let o=this[t],s=1,a=0;for(;++a=s&&(o-=Math.pow(2,8*e)),o},i.prototype.readIntBE=function(t,e,n){t=t>>>0,e=e>>>0,n||P(t,e,this.length);let o=e,s=1,a=this[t+--o];for(;o>0&&(s*=256);)a+=this[t+--o]*s;return s*=128,a>=s&&(a-=Math.pow(2,8*e)),a},i.prototype.readInt8=function(t,e){return t=t>>>0,e||P(t,1,this.length),this[t]&128?(255-this[t]+1)*-1:this[t]},i.prototype.readInt16LE=function(t,e){t=t>>>0,e||P(t,2,this.length);let n=this[t]|this[t+1]<<8;return n&32768?n|4294901760:n},i.prototype.readInt16BE=function(t,e){t=t>>>0,e||P(t,2,this.length);let n=this[t+1]|this[t]<<8;return n&32768?n|4294901760:n},i.prototype.readInt32LE=function(t,e){return t=t>>>0,e||P(t,4,this.length),this[t]|this[t+1]<<8|this[t+2]<<16|this[t+3]<<24},i.prototype.readInt32BE=function(t,e){return t=t>>>0,e||P(t,4,this.length),this[t]<<24|this[t+1]<<16|this[t+2]<<8|this[t+3]},i.prototype.readBigInt64LE=X(function(t){t=t>>>0,et(t,"offset");let e=this[t],n=this[t+7];(e===void 0||n===void 0)&&nt(t,this.length-8);let o=this[t+4]+this[t+5]*2**8+this[t+6]*2**16+(n<<24);return (BigInt(o)<>>0,et(t,"offset");let e=this[t],n=this[t+7];(e===void 0||n===void 0)&&nt(t,this.length-8);let o=(e<<24)+this[++t]*2**16+this[++t]*2**8+this[++t];return (BigInt(o)<>>0,e||P(t,4,this.length),u.read(this,t,!0,23,4)},i.prototype.readFloatBE=function(t,e){return t=t>>>0,e||P(t,4,this.length),u.read(this,t,!1,23,4)},i.prototype.readDoubleLE=function(t,e){return t=t>>>0,e||P(t,8,this.length),u.read(this,t,!0,52,8)},i.prototype.readDoubleBE=function(t,e){return t=t>>>0,e||P(t,8,this.length),u.read(this,t,!1,52,8)};function q(r,t,e,n,o,s){if(!i.isBuffer(r))throw new TypeError('"buffer" argument must be a Buffer instance');if(t>o||tr.length)throw new RangeError("Index out of range")}i.prototype.writeUintLE=i.prototype.writeUIntLE=function(t,e,n,o){if(t=+t,e=e>>>0,n=n>>>0,!o){let w=Math.pow(2,8*n)-1;q(this,t,e,n,w,0);}let s=1,a=0;for(this[e]=t&255;++a>>0,n=n>>>0,!o){let w=Math.pow(2,8*n)-1;q(this,t,e,n,w,0);}let s=n-1,a=1;for(this[e+s]=t&255;--s>=0&&(a*=256);)this[e+s]=t/a&255;return e+n},i.prototype.writeUint8=i.prototype.writeUInt8=function(t,e,n){return t=+t,e=e>>>0,n||q(this,t,e,1,255,0),this[e]=t&255,e+1},i.prototype.writeUint16LE=i.prototype.writeUInt16LE=function(t,e,n){return t=+t,e=e>>>0,n||q(this,t,e,2,65535,0),this[e]=t&255,this[e+1]=t>>>8,e+2},i.prototype.writeUint16BE=i.prototype.writeUInt16BE=function(t,e,n){return t=+t,e=e>>>0,n||q(this,t,e,2,65535,0),this[e]=t>>>8,this[e+1]=t&255,e+2},i.prototype.writeUint32LE=i.prototype.writeUInt32LE=function(t,e,n){return t=+t,e=e>>>0,n||q(this,t,e,4,4294967295,0),this[e+3]=t>>>24,this[e+2]=t>>>16,this[e+1]=t>>>8,this[e]=t&255,e+4},i.prototype.writeUint32BE=i.prototype.writeUInt32BE=function(t,e,n){return t=+t,e=e>>>0,n||q(this,t,e,4,4294967295,0),this[e]=t>>>24,this[e+1]=t>>>16,this[e+2]=t>>>8,this[e+3]=t&255,e+4};function Pt(r,t,e,n,o){$t(t,n,o,r,e,7);let s=Number(t&BigInt(4294967295));r[e++]=s,s=s>>8,r[e++]=s,s=s>>8,r[e++]=s,s=s>>8,r[e++]=s;let a=Number(t>>BigInt(32)&BigInt(4294967295));return r[e++]=a,a=a>>8,r[e++]=a,a=a>>8,r[e++]=a,a=a>>8,r[e++]=a,e}function Lt(r,t,e,n,o){$t(t,n,o,r,e,7);let s=Number(t&BigInt(4294967295));r[e+7]=s,s=s>>8,r[e+6]=s,s=s>>8,r[e+5]=s,s=s>>8,r[e+4]=s;let a=Number(t>>BigInt(32)&BigInt(4294967295));return r[e+3]=a,a=a>>8,r[e+2]=a,a=a>>8,r[e+1]=a,a=a>>8,r[e]=a,e+8}i.prototype.writeBigUInt64LE=X(function(t,e=0){return Pt(this,t,e,BigInt(0),BigInt("0xffffffffffffffff"))}),i.prototype.writeBigUInt64BE=X(function(t,e=0){return Lt(this,t,e,BigInt(0),BigInt("0xffffffffffffffff"))}),i.prototype.writeIntLE=function(t,e,n,o){if(t=+t,e=e>>>0,!o){let k=Math.pow(2,8*n-1);q(this,t,e,n,k-1,-k);}let s=0,a=1,w=0;for(this[e]=t&255;++s>0)-w&255;return e+n},i.prototype.writeIntBE=function(t,e,n,o){if(t=+t,e=e>>>0,!o){let k=Math.pow(2,8*n-1);q(this,t,e,n,k-1,-k);}let s=n-1,a=1,w=0;for(this[e+s]=t&255;--s>=0&&(a*=256);)t<0&&w===0&&this[e+s+1]!==0&&(w=1),this[e+s]=(t/a>>0)-w&255;return e+n},i.prototype.writeInt8=function(t,e,n){return t=+t,e=e>>>0,n||q(this,t,e,1,127,-128),t<0&&(t=255+t+1),this[e]=t&255,e+1},i.prototype.writeInt16LE=function(t,e,n){return t=+t,e=e>>>0,n||q(this,t,e,2,32767,-32768),this[e]=t&255,this[e+1]=t>>>8,e+2},i.prototype.writeInt16BE=function(t,e,n){return t=+t,e=e>>>0,n||q(this,t,e,2,32767,-32768),this[e]=t>>>8,this[e+1]=t&255,e+2},i.prototype.writeInt32LE=function(t,e,n){return t=+t,e=e>>>0,n||q(this,t,e,4,2147483647,-2147483648),this[e]=t&255,this[e+1]=t>>>8,this[e+2]=t>>>16,this[e+3]=t>>>24,e+4},i.prototype.writeInt32BE=function(t,e,n){return t=+t,e=e>>>0,n||q(this,t,e,4,2147483647,-2147483648),t<0&&(t=4294967295+t+1),this[e]=t>>>24,this[e+1]=t>>>16,this[e+2]=t>>>8,this[e+3]=t&255,e+4},i.prototype.writeBigInt64LE=X(function(t,e=0){return Pt(this,t,e,-BigInt("0x8000000000000000"),BigInt("0x7fffffffffffffff"))}),i.prototype.writeBigInt64BE=X(function(t,e=0){return Lt(this,t,e,-BigInt("0x8000000000000000"),BigInt("0x7fffffffffffffff"))});function Nt(r,t,e,n,o,s){if(e+n>r.length)throw new RangeError("Index out of range");if(e<0)throw new RangeError("Index out of range")}function Wt(r,t,e,n,o){return t=+t,e=e>>>0,o||Nt(r,t,e,4),u.write(r,t,e,n,23,4),e+4}i.prototype.writeFloatLE=function(t,e,n){return Wt(this,t,e,!0,n)},i.prototype.writeFloatBE=function(t,e,n){return Wt(this,t,e,!1,n)};function Mt(r,t,e,n,o){return t=+t,e=e>>>0,o||Nt(r,t,e,8),u.write(r,t,e,n,52,8),e+8}i.prototype.writeDoubleLE=function(t,e,n){return Mt(this,t,e,!0,n)},i.prototype.writeDoubleBE=function(t,e,n){return Mt(this,t,e,!1,n)},i.prototype.copy=function(t,e,n,o){if(!i.isBuffer(t))throw new TypeError("argument should be a Buffer");if(n||(n=0),!o&&o!==0&&(o=this.length),e>=t.length&&(e=t.length),e||(e=0),o>0&&o=this.length)throw new RangeError("Index out of range");if(o<0)throw new RangeError("sourceEnd out of bounds");o>this.length&&(o=this.length),t.length-e>>0,n=n===void 0?this.length:n>>>0,t||(t=0);let s;if(typeof t=="number")for(s=e;s2**32?o=Ot(String(e)):typeof e=="bigint"&&(o=String(e),(e>BigInt(2)**BigInt(32)||e<-(BigInt(2)**BigInt(32)))&&(o=Ot(o)),o+="n"),n+=` It must be ${t}. Received ${o}`,n},RangeError);function Ot(r){let t="",e=r.length,n=r[0]==="-"?1:0;for(;e>=n+4;e-=3)t=`_${r.slice(e-3,e)}${t}`;return `${r.slice(0,e)}${t}`}function kr(r,t,e){et(t,"offset"),(r[t]===void 0||r[t+e]===void 0)&&nt(t,r.length-(e+1));}function $t(r,t,e,n,o,s){if(r>e||r= 0${a} and < 2${a} ** ${(s+1)*8}${a}`:w=`>= -(2${a} ** ${(s+1)*8-1}${a}) and < 2 ** ${(s+1)*8-1}${a}`,new tt.ERR_OUT_OF_RANGE("value",w,r)}kr(n,o,s);}function et(r,t){if(typeof r!="number")throw new tt.ERR_INVALID_ARG_TYPE(t,"number",r)}function nt(r,t,e){throw Math.floor(r)!==r?(et(r,e),new tt.ERR_OUT_OF_RANGE("offset","an integer",r)):t<0?new tt.ERR_BUFFER_OUT_OF_BOUNDS:new tt.ERR_OUT_OF_RANGE("offset",`>= ${0} and <= ${t}`,r)}let xr=/[^+/0-9A-Za-z-_]/g;function vr(r){if(r=r.split("=")[0],r=r.trim().replace(xr,""),r.length<2)return "";for(;r.length%4!==0;)r=r+"=";return r}function gt(r,t){t=t||1/0;let e,n=r.length,o=null,s=[];for(let a=0;a55295&&e<57344){if(!o){if(e>56319){(t-=3)>-1&&s.push(239,191,189);continue}else if(a+1===n){(t-=3)>-1&&s.push(239,191,189);continue}o=e;continue}if(e<56320){(t-=3)>-1&&s.push(239,191,189),o=e;continue}e=(o-55296<<10|e-56320)+65536;}else o&&(t-=3)>-1&&s.push(239,191,189);if(o=null,e<128){if((t-=1)<0)break;s.push(e);}else if(e<2048){if((t-=2)<0)break;s.push(e>>6|192,e&63|128);}else if(e<65536){if((t-=3)<0)break;s.push(e>>12|224,e>>6&63|128,e&63|128);}else if(e<1114112){if((t-=4)<0)break;s.push(e>>18|240,e>>12&63|128,e>>6&63|128,e&63|128);}else throw new Error("Invalid code point")}return s}function Sr(r){let t=[];for(let e=0;e>8,o=e%256,s.push(o),s.push(n);return s}function Ft(r){return h.toByteArray(vr(r))}function ut(r,t,e,n){let o;for(o=0;o=t.length||o>=r.length);++o)t[o+e]=r[o];return o}function Y(r,t){return r instanceof t||r!=null&&r.constructor!=null&&r.constructor.name!=null&&r.constructor.name===t.name}function Et(r){return r!==r}let Tr=function(){let r="0123456789abcdef",t=new Array(256);for(let e=0;e<16;++e){let n=e*16;for(let o=0;o<16;++o)t[n+o]=r[e]+r[o];}return t}();function X(r){return typeof BigInt=="undefined"?Cr:r}function Cr(){throw new Error("BigInt not supported")}return z}var ot,sr,ft,ur,z,cr,Z,G,ar=it(()=>{T();R();C();ot={},sr=!1;ft={},ur=!1;z={},cr=!1;Z=Dr();Z.Buffer;Z.SlowBuffer;Z.INSPECT_MAX_BYTES;Z.kMaxLength;G=Z.Buffer,Z.INSPECT_MAX_BYTES,Z.kMaxLength;});var R=it(()=>{ar();});var vt=Wr((un,xt)=>{T();R();C();var jr=Object.prototype.hasOwnProperty,O="~";function st(){}Object.create&&(st.prototype=Object.create(null),new st().__proto__||(O=!1));function Yr(h,u,c){this.fn=h,this.context=u,this.once=c||!1;}function hr(h,u,c,l,p){if(typeof c!="function")throw new TypeError("The listener must be a function");var f=new Yr(c,l||h,p),i=O?O+u:u;return h._events[i]?h._events[i].fn?h._events[i]=[h._events[i],f]:h._events[i].push(f):(h._events[i]=f,h._eventsCount++),h}function dt(h,u){--h._eventsCount===0?h._events=new st:delete h._events[u];}function W(){this._events=new st,this._eventsCount=0;}W.prototype.eventNames=function(){var u=[],c,l;if(this._eventsCount===0)return u;for(l in c=this._events)jr.call(c,l)&&u.push(O?l.slice(1):l);return Object.getOwnPropertySymbols?u.concat(Object.getOwnPropertySymbols(c)):u};W.prototype.listeners=function(u){var c=O?O+u:u,l=this._events[c];if(!l)return [];if(l.fn)return [l.fn];for(var p=0,f=l.length,i=new Array(f);pthis.emit("open"),this.socket.onmessage=f=>this.emit("message",f.data),this.socket.onerror=f=>this.emit("error",f),this.socket.onclose=f=>{this.emit("close",f.code,f.reason);};}send(c,l,p){let f=p||l;try{this.socket.send(c),f();}catch(i){f(i);}}close(c,l){this.socket.close(c,l);}addEventListener(c,l,p){this.socket.addEventListener(c,l,p);}};function lr(h,u){return new St(h,u)}T();R();C();var fr=jt(vt());T();R();C();var yt=class{encode(u){return JSON.stringify(u)}decode(u){return JSON.parse(u)}};var mt=class extends fr.EventEmitter{constructor(c,l="ws://localhost:8080",m={},b,B){var L=m,{autoconnect:p=!0,reconnect:f=!0,reconnect_interval:i=1e3,max_reconnects:E=5}=L,d=Dt(L,["autoconnect","reconnect","reconnect_interval","max_reconnects"]);super();U(this,"address");U(this,"rpc_id");U(this,"queue");U(this,"options");U(this,"autoconnect");U(this,"ready");U(this,"reconnect");U(this,"reconnect_timer_id");U(this,"reconnect_interval");U(this,"max_reconnects");U(this,"rest_options");U(this,"current_reconnects");U(this,"generate_request_id");U(this,"socket");U(this,"webSocketFactory");U(this,"dataPack");this.webSocketFactory=c,this.queue={},this.rpc_id=0,this.address=l,this.autoconnect=p,this.ready=!1,this.reconnect=f,this.reconnect_timer_id=void 0,this.reconnect_interval=i,this.max_reconnects=E,this.rest_options=d,this.current_reconnects=0,this.generate_request_id=b||(()=>++this.rpc_id),B?this.dataPack=B:this.dataPack=new yt,this.autoconnect&&this._connect(this.address,_t({autoconnect:this.autoconnect,reconnect:this.reconnect,reconnect_interval:this.reconnect_interval,max_reconnects:this.max_reconnects},this.rest_options));}connect(){this.socket||this._connect(this.address,_t({autoconnect:this.autoconnect,reconnect:this.reconnect,reconnect_interval:this.reconnect_interval,max_reconnects:this.max_reconnects},this.rest_options));}call(c,l,p,f){return !f&&typeof p=="object"&&(f=p,p=null),new Promise((i,E)=>{if(!this.ready)return E(new Error("socket not ready"));let d=this.generate_request_id(c,l),b={jsonrpc:"2.0",method:c,params:l||void 0,id:d};this.socket.send(this.dataPack.encode(b),f,B=>{if(B)return E(B);this.queue[d]={promise:[i,E]},p&&(this.queue[d].timeout=setTimeout(()=>{delete this.queue[d],E(new Error("reply timeout"));},p));});})}async login(c){let l=await this.call("rpc.login",c);if(!l)throw new Error("authentication failed");return l}async listMethods(){return await this.call("__listMethods")}notify(c,l){return new Promise((p,f)=>{if(!this.ready)return f(new Error("socket not ready"));let i={jsonrpc:"2.0",method:c,params:l};this.socket.send(this.dataPack.encode(i),E=>{if(E)return f(E);p();});})}async subscribe(c){typeof c=="string"&&(c=[c]);let l=await this.call("rpc.on",c);if(typeof c=="string"&&l[c]!=="ok")throw new Error("Failed subscribing to an event '"+c+"' with: "+l[c]);return l}async unsubscribe(c){typeof c=="string"&&(c=[c]);let l=await this.call("rpc.off",c);if(typeof c=="string"&&l[c]!=="ok")throw new Error("Failed unsubscribing from an event with: "+l);return l}close(c,l){this.socket.close(c||1e3,l);}setAutoReconnect(c){this.reconnect=c;}setReconnectInterval(c){this.reconnect_interval=c;}setMaxReconnects(c){this.max_reconnects=c;}_connect(c,l){clearTimeout(this.reconnect_timer_id),this.socket=this.webSocketFactory(c,l),this.socket.addEventListener("open",()=>{this.ready=!0,this.emit("open"),this.current_reconnects=0;}),this.socket.addEventListener("message",({data:p})=>{p instanceof ArrayBuffer&&(p=G.from(p).toString());try{p=this.dataPack.decode(p);}catch(f){return}if(p.notification&&this.listeners(p.notification).length){if(!Object.keys(p.params).length)return this.emit(p.notification);let f=[p.notification];if(p.params.constructor===Object)f.push(p.params);else for(let i=0;i{this.emit.apply(this,f);})}if(!this.queue[p.id])return p.method?Promise.resolve().then(()=>{this.emit(p.method,p==null?void 0:p.params);}):void 0;"error"in p=="result"in p&&this.queue[p.id].promise[1](new Error('Server response malformed. Response must include either "result" or "error", but not both.')),this.queue[p.id].timeout&&clearTimeout(this.queue[p.id].timeout),p.error?this.queue[p.id].promise[1](p.error):this.queue[p.id].promise[0](p.result),delete this.queue[p.id];}),this.socket.addEventListener("error",p=>this.emit("error",p)),this.socket.addEventListener("close",({code:p,reason:f})=>{this.ready&&setTimeout(()=>this.emit("close",p,f),0),this.ready=!1,this.socket=void 0,p!==1e3&&(this.current_reconnects++,this.reconnect&&(this.max_reconnects>this.current_reconnects||this.max_reconnects===0)&&(this.reconnect_timer_id=setTimeout(()=>this._connect(c,l),this.reconnect_interval)));});}};T();R();C();var Ut=class extends mt{constructor(u="ws://localhost:8080",{autoconnect:c=!0,reconnect:l=!0,reconnect_interval:p=1e3,max_reconnects:f=5}={},i){super(lr,u,{autoconnect:c,reconnect:l,reconnect_interval:p,max_reconnects:f},i);}};/*! Bundled license information: + + @jspm/core/nodelibs/browser/buffer.js: + (*! ieee754. BSD-3-Clause License. Feross Aboukhadijeh *) + */ + + exports.Client = Ut; + + return exports; + +})({}); diff --git a/dist/index.browser.cjs b/dist/index.browser.cjs index 0cacde8..7e2266a 100644 --- a/dist/index.browser.cjs +++ b/dist/index.browser.cjs @@ -1,19 +1,389 @@ -"use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.Client = void 0; -const websocket_browser_cjs_1 = __importDefault(require("./lib/client/websocket.browser.cjs")); -const client_cjs_1 = __importDefault(require("./lib/client.cjs")); -class Client extends client_cjs_1.default { - constructor(address = "ws://localhost:8080", { autoconnect = true, reconnect = true, reconnect_interval = 1000, max_reconnects = 5 } = {}, generate_request_id) { - super(websocket_browser_cjs_1.default, address, { - autoconnect, - reconnect, - reconnect_interval, - max_reconnects - }, generate_request_id); +'use strict'; + +var buffer = require('buffer'); +var eventemitter3 = require('eventemitter3'); + +// node_modules/esbuild-plugin-polyfill-node/polyfills/buffer.js +var WebSocketBrowserImpl = class extends eventemitter3.EventEmitter { + socket; + /** Instantiate a WebSocket class + * @constructor + * @param {String} address - url to a websocket server + * @param {(Object)} options - websocket options + * @param {(String|Array)} protocols - a list of protocols + * @return {WebSocketBrowserImpl} - returns a WebSocket instance + */ + constructor(address, options, protocols) { + super(); + this.socket = new window.WebSocket(address, protocols); + this.socket.onopen = () => this.emit("open"); + this.socket.onmessage = (event) => this.emit("message", event.data); + this.socket.onerror = (error) => this.emit("error", error); + this.socket.onclose = (event) => { + this.emit("close", event.code, event.reason); + }; + } + /** + * Sends data through a websocket connection + * @method + * @param {(String|Object)} data - data to be sent via websocket + * @param {Object} optionsOrCallback - ws options + * @param {Function} callback - a callback called once the data is sent + * @return {Undefined} + */ + send(data, optionsOrCallback, callback) { + const cb = callback || optionsOrCallback; + try { + this.socket.send(data); + cb(); + } catch (error) { + cb(error); } + } + /** + * Closes an underlying socket + * @method + * @param {Number} code - status code explaining why the connection is being closed + * @param {String} reason - a description why the connection is closing + * @return {Undefined} + * @throws {Error} + */ + close(code, reason) { + this.socket.close(code, reason); + } + addEventListener(type, listener, options) { + this.socket.addEventListener(type, listener, options); + } +}; +function WebSocket(address, options) { + return new WebSocketBrowserImpl(address, options); } + +// src/lib/utils.ts +var DefaultDataPack = class { + encode(value) { + return JSON.stringify(value); + } + decode(value) { + return JSON.parse(value); + } +}; + +// src/lib/client.ts +var CommonClient = class extends eventemitter3.EventEmitter { + address; + rpc_id; + queue; + options; + autoconnect; + ready; + reconnect; + reconnect_timer_id; + reconnect_interval; + max_reconnects; + rest_options; + current_reconnects; + generate_request_id; + socket; + webSocketFactory; + dataPack; + /** + * Instantiate a Client class. + * @constructor + * @param {webSocketFactory} webSocketFactory - factory method for WebSocket + * @param {String} address - url to a websocket server + * @param {Object} options - ws options object with reconnect parameters + * @param {Function} generate_request_id - custom generation request Id + * @param {DataPack} dataPack - data pack contains encoder and decoder + * @return {CommonClient} + */ + constructor(webSocketFactory, address = "ws://localhost:8080", { + autoconnect = true, + reconnect = true, + reconnect_interval = 1e3, + max_reconnects = 5, + ...rest_options + } = {}, generate_request_id, dataPack) { + super(); + this.webSocketFactory = webSocketFactory; + this.queue = {}; + this.rpc_id = 0; + this.address = address; + this.autoconnect = autoconnect; + this.ready = false; + this.reconnect = reconnect; + this.reconnect_timer_id = void 0; + this.reconnect_interval = reconnect_interval; + this.max_reconnects = max_reconnects; + this.rest_options = rest_options; + this.current_reconnects = 0; + this.generate_request_id = generate_request_id || (() => ++this.rpc_id); + if (!dataPack) this.dataPack = new DefaultDataPack(); + else this.dataPack = dataPack; + if (this.autoconnect) + this._connect(this.address, { + autoconnect: this.autoconnect, + reconnect: this.reconnect, + reconnect_interval: this.reconnect_interval, + max_reconnects: this.max_reconnects, + ...this.rest_options + }); + } + /** + * Connects to a defined server if not connected already. + * @method + * @return {Undefined} + */ + connect() { + if (this.socket) return; + this._connect(this.address, { + autoconnect: this.autoconnect, + reconnect: this.reconnect, + reconnect_interval: this.reconnect_interval, + max_reconnects: this.max_reconnects, + ...this.rest_options + }); + } + /** + * Calls a registered RPC method on server. + * @method + * @param {String} method - RPC method name + * @param {Object|Array} params - optional method parameters + * @param {Number} timeout - RPC reply timeout value + * @param {Object} ws_opts - options passed to ws + * @return {Promise} + */ + call(method, params, timeout, ws_opts) { + if (!ws_opts && "object" === typeof timeout) { + ws_opts = timeout; + timeout = null; + } + return new Promise((resolve, reject) => { + if (!this.ready) return reject(new Error("socket not ready")); + const rpc_id = this.generate_request_id(method, params); + const message = { + jsonrpc: "2.0", + method, + params: params || void 0, + id: rpc_id + }; + this.socket.send(this.dataPack.encode(message), ws_opts, (error) => { + if (error) return reject(error); + this.queue[rpc_id] = { promise: [resolve, reject] }; + if (timeout) { + this.queue[rpc_id].timeout = setTimeout(() => { + delete this.queue[rpc_id]; + reject(new Error("reply timeout")); + }, timeout); + } + }); + }); + } + /** + * Logins with the other side of the connection. + * @method + * @param {Object} params - Login credentials object + * @return {Promise} + */ + async login(params) { + const resp = await this.call("rpc.login", params); + if (!resp) throw new Error("authentication failed"); + return resp; + } + /** + * Fetches a list of client's methods registered on server. + * @method + * @return {Array} + */ + async listMethods() { + return await this.call("__listMethods"); + } + /** + * Sends a JSON-RPC 2.0 notification to server. + * @method + * @param {String} method - RPC method name + * @param {Object} params - optional method parameters + * @return {Promise} + */ + notify(method, params) { + return new Promise((resolve, reject) => { + if (!this.ready) return reject(new Error("socket not ready")); + const message = { + jsonrpc: "2.0", + method, + params + }; + this.socket.send(this.dataPack.encode(message), (error) => { + if (error) return reject(error); + resolve(); + }); + }); + } + /** + * Subscribes for a defined event. + * @method + * @param {String|Array} event - event name + * @return {Undefined} + * @throws {Error} + */ + async subscribe(event) { + if (typeof event === "string") event = [event]; + const result = await this.call("rpc.on", event); + if (typeof event === "string" && result[event] !== "ok") + throw new Error( + "Failed subscribing to an event '" + event + "' with: " + result[event] + ); + return result; + } + /** + * Unsubscribes from a defined event. + * @method + * @param {String|Array} event - event name + * @return {Undefined} + * @throws {Error} + */ + async unsubscribe(event) { + if (typeof event === "string") event = [event]; + const result = await this.call("rpc.off", event); + if (typeof event === "string" && result[event] !== "ok") + throw new Error("Failed unsubscribing from an event with: " + result); + return result; + } + /** + * Closes a WebSocket connection gracefully. + * @method + * @param {Number} code - socket close code + * @param {String} data - optional data to be sent before closing + * @return {Undefined} + */ + close(code, data) { + this.socket.close(code || 1e3, data); + } + /** + * Enable / disable automatic reconnection. + * @method + * @param {Boolean} reconnect - enable / disable reconnection + * @return {Undefined} + */ + setAutoReconnect(reconnect) { + this.reconnect = reconnect; + } + /** + * Set the interval between reconnection attempts. + * @method + * @param {Number} interval - reconnection interval in milliseconds + * @return {Undefined} + */ + setReconnectInterval(interval) { + this.reconnect_interval = interval; + } + /** + * Set the maximum number of reconnection attempts. + * @method + * @param {Number} max_reconnects - maximum reconnection attempts + * @return {Undefined} + */ + setMaxReconnects(max_reconnects) { + this.max_reconnects = max_reconnects; + } + /** + * Connection/Message handler. + * @method + * @private + * @param {String} address - WebSocket API address + * @param {Object} options - ws options object + * @return {Undefined} + */ + _connect(address, options) { + clearTimeout(this.reconnect_timer_id); + this.socket = this.webSocketFactory(address, options); + this.socket.addEventListener("open", () => { + this.ready = true; + this.emit("open"); + this.current_reconnects = 0; + }); + this.socket.addEventListener("message", ({ data: message }) => { + if (message instanceof ArrayBuffer) + message = buffer.Buffer.from(message).toString(); + try { + message = this.dataPack.decode(message); + } catch (error) { + return; + } + if (message.notification && this.listeners(message.notification).length) { + if (!Object.keys(message.params).length) + return this.emit(message.notification); + const args = [message.notification]; + if (message.params.constructor === Object) args.push(message.params); + else + for (let i = 0; i < message.params.length; i++) + args.push(message.params[i]); + return Promise.resolve().then(() => { + this.emit.apply(this, args); + }); + } + if (!this.queue[message.id]) { + if (message.method) { + return Promise.resolve().then(() => { + this.emit(message.method, message?.params); + }); + } + return; + } + if ("error" in message === "result" in message) + this.queue[message.id].promise[1]( + new Error( + 'Server response malformed. Response must include either "result" or "error", but not both.' + ) + ); + if (this.queue[message.id].timeout) + clearTimeout(this.queue[message.id].timeout); + if (message.error) this.queue[message.id].promise[1](message.error); + else this.queue[message.id].promise[0](message.result); + delete this.queue[message.id]; + }); + this.socket.addEventListener("error", (error) => this.emit("error", error)); + this.socket.addEventListener("close", ({ code, reason }) => { + if (this.ready) + setTimeout(() => this.emit("close", code, reason), 0); + this.ready = false; + this.socket = void 0; + if (code === 1e3) return; + this.current_reconnects++; + if (this.reconnect && (this.max_reconnects > this.current_reconnects || this.max_reconnects === 0)) + this.reconnect_timer_id = setTimeout( + () => this._connect(address, options), + this.reconnect_interval + ); + }); + } +}; + +// src/index.browser.ts +var Client = class extends CommonClient { + constructor(address = "ws://localhost:8080", { + autoconnect = true, + reconnect = true, + reconnect_interval = 1e3, + max_reconnects = 5 + } = {}, generate_request_id) { + super( + WebSocket, + address, + { + autoconnect, + reconnect, + reconnect_interval, + max_reconnects + }, + generate_request_id + ); + } +}; + exports.Client = Client; +exports.CommonClient = CommonClient; +exports.DefaultDataPack = DefaultDataPack; +exports.WebSocket = WebSocket; +//# sourceMappingURL=out.js.map +//# sourceMappingURL=index.browser.cjs.map \ No newline at end of file diff --git a/dist/index.browser.cjs.map b/dist/index.browser.cjs.map new file mode 100644 index 0000000..d720c5f --- /dev/null +++ b/dist/index.browser.cjs.map @@ -0,0 +1 @@ +{"version":3,"sources":["../node_modules/esbuild-plugin-polyfill-node/polyfills/buffer.js","../src/lib/client/websocket.browser.ts","../src/lib/client.ts","../src/lib/utils.ts","../src/index.browser.ts"],"names":["EventEmitter"],"mappings":"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","sourcesContent":["export { Buffer } from \"buffer\";\n","/**\n * WebSocket implements a browser-side WebSocket specification.\n * @module Client\n */\n\n\"use strict\"\n\nimport { EventEmitter } from \"eventemitter3\"\n\nimport {\n BrowserWebSocketType,\n NodeWebSocketType,\n IWSClientAdditionalOptions,\n} from \"./client.types.js\"\n\nclass WebSocketBrowserImpl extends EventEmitter\n{\n socket: BrowserWebSocketType\n\n /** Instantiate a WebSocket class\n * @constructor\n * @param {String} address - url to a websocket server\n * @param {(Object)} options - websocket options\n * @param {(String|Array)} protocols - a list of protocols\n * @return {WebSocketBrowserImpl} - returns a WebSocket instance\n */\n constructor(address: string, options: {}, protocols?: string | string[])\n {\n super()\n\n this.socket = new window.WebSocket(address, protocols)\n\n this.socket.onopen = () => this.emit(\"open\")\n this.socket.onmessage = (event) => this.emit(\"message\", event.data)\n this.socket.onerror = (error) => this.emit(\"error\", error)\n this.socket.onclose = (event) =>\n {\n this.emit(\"close\", event.code, event.reason)\n }\n }\n\n /**\n * Sends data through a websocket connection\n * @method\n * @param {(String|Object)} data - data to be sent via websocket\n * @param {Object} optionsOrCallback - ws options\n * @param {Function} callback - a callback called once the data is sent\n * @return {Undefined}\n */\n send(\n data: Parameters[0],\n optionsOrCallback: (\n error?: Error\n ) => void | Parameters[1],\n callback?: () => void\n )\n {\n const cb = callback || optionsOrCallback\n\n try\n {\n this.socket.send(data)\n cb()\n }\n catch (error)\n {\n cb(error)\n }\n }\n\n /**\n * Closes an underlying socket\n * @method\n * @param {Number} code - status code explaining why the connection is being closed\n * @param {String} reason - a description why the connection is closing\n * @return {Undefined}\n * @throws {Error}\n */\n close(code?: number, reason?: string)\n {\n this.socket.close(code, reason)\n }\n\n addEventListener(\n type: K,\n listener: (ev: WebSocketEventMap[K]) => any,\n options?: boolean | AddEventListenerOptions\n ): void\n {\n this.socket.addEventListener(type, listener, options)\n }\n}\n\n/**\n * factory method for common WebSocket instance\n * @method\n * @param {String} address - url to a websocket server\n * @param {(Object)} options - websocket options\n * @return {Undefined}\n */\nexport function WebSocket(\n address: string,\n options: IWSClientAdditionalOptions\n)\n{\n return new WebSocketBrowserImpl(address, options)\n}\n","/**\n * \"Client\" wraps \"ws\" or a browser-implemented \"WebSocket\" library\n * according to the environment providing JSON RPC 2.0 support on top.\n * @module Client\n */\n\n\"use strict\"\n\nimport NodeWebSocket from \"ws\"\nimport { EventEmitter } from \"eventemitter3\"\nimport {\n ICommonWebSocket,\n IWSClientAdditionalOptions,\n NodeWebSocketType,\n ICommonWebSocketFactory,\n} from \"./client/client.types.js\"\n\nimport { DataPack, DefaultDataPack } from \"./utils.js\"\n\ninterface IQueueElement {\n promise: [\n Parameters[0]>[0],\n Parameters[0]>[1]\n ];\n timeout?: ReturnType;\n}\n\nexport interface IQueue {\n [x: number]: IQueueElement;\n}\n\nexport interface IWSRequestParams {\n [x: string]: any;\n [x: number]: any;\n}\n\nexport class CommonClient extends EventEmitter\n{\n private address: string\n private rpc_id: number\n private queue: IQueue\n private options: IWSClientAdditionalOptions & NodeWebSocket.ClientOptions\n private autoconnect: boolean\n private ready: boolean\n private reconnect: boolean\n private reconnect_timer_id: NodeJS.Timeout\n private reconnect_interval: number\n private max_reconnects: number\n private rest_options: IWSClientAdditionalOptions &\n NodeWebSocket.ClientOptions\n private current_reconnects: number\n private generate_request_id: (\n method: string,\n params: object | Array\n ) => number\n private socket: ICommonWebSocket\n private webSocketFactory: ICommonWebSocketFactory\n private dataPack: DataPack\n\n /**\n * Instantiate a Client class.\n * @constructor\n * @param {webSocketFactory} webSocketFactory - factory method for WebSocket\n * @param {String} address - url to a websocket server\n * @param {Object} options - ws options object with reconnect parameters\n * @param {Function} generate_request_id - custom generation request Id\n * @param {DataPack} dataPack - data pack contains encoder and decoder\n * @return {CommonClient}\n */\n constructor(\n webSocketFactory: ICommonWebSocketFactory,\n address = \"ws://localhost:8080\",\n {\n autoconnect = true,\n reconnect = true,\n reconnect_interval = 1000,\n max_reconnects = 5,\n ...rest_options\n } = {},\n generate_request_id?: (\n method: string,\n params: object | Array\n ) => number,\n dataPack?: DataPack\n )\n {\n super()\n\n this.webSocketFactory = webSocketFactory\n\n this.queue = {}\n this.rpc_id = 0\n\n this.address = address\n this.autoconnect = autoconnect\n this.ready = false\n this.reconnect = reconnect\n this.reconnect_timer_id = undefined\n this.reconnect_interval = reconnect_interval\n this.max_reconnects = max_reconnects\n this.rest_options = rest_options\n this.current_reconnects = 0\n this.generate_request_id = generate_request_id || (() => ++this.rpc_id)\n\n if (!dataPack) this.dataPack = new DefaultDataPack()\n else this.dataPack = dataPack\n\n if (this.autoconnect)\n this._connect(this.address, {\n autoconnect: this.autoconnect,\n reconnect: this.reconnect,\n reconnect_interval: this.reconnect_interval,\n max_reconnects: this.max_reconnects,\n ...this.rest_options,\n })\n }\n\n /**\n * Connects to a defined server if not connected already.\n * @method\n * @return {Undefined}\n */\n connect()\n {\n if (this.socket) return\n\n this._connect(this.address, {\n autoconnect: this.autoconnect,\n reconnect: this.reconnect,\n reconnect_interval: this.reconnect_interval,\n max_reconnects: this.max_reconnects,\n ...this.rest_options,\n })\n }\n\n /**\n * Calls a registered RPC method on server.\n * @method\n * @param {String} method - RPC method name\n * @param {Object|Array} params - optional method parameters\n * @param {Number} timeout - RPC reply timeout value\n * @param {Object} ws_opts - options passed to ws\n * @return {Promise}\n */\n call(\n method: string,\n params?: IWSRequestParams,\n timeout?: number,\n ws_opts?: Parameters[1]\n )\n {\n if (!ws_opts && \"object\" === typeof timeout)\n {\n ws_opts = timeout\n timeout = null\n }\n\n return new Promise((resolve, reject) =>\n {\n if (!this.ready) return reject(new Error(\"socket not ready\"))\n\n const rpc_id = this.generate_request_id(method, params)\n\n const message = {\n jsonrpc: \"2.0\",\n method: method,\n params: params || undefined,\n id: rpc_id,\n }\n\n this.socket.send(this.dataPack.encode(message), ws_opts, (error) =>\n {\n if (error) return reject(error)\n\n this.queue[rpc_id] = { promise: [resolve, reject] }\n\n if (timeout)\n {\n this.queue[rpc_id].timeout = setTimeout(() =>\n {\n delete this.queue[rpc_id]\n reject(new Error(\"reply timeout\"))\n }, timeout)\n }\n })\n })\n }\n\n /**\n * Logins with the other side of the connection.\n * @method\n * @param {Object} params - Login credentials object\n * @return {Promise}\n */\n async login(params: IWSRequestParams)\n {\n const resp = await this.call(\"rpc.login\", params)\n\n if (!resp) throw new Error(\"authentication failed\")\n\n return resp\n }\n\n /**\n * Fetches a list of client's methods registered on server.\n * @method\n * @return {Array}\n */\n async listMethods()\n {\n return await this.call(\"__listMethods\")\n }\n\n /**\n * Sends a JSON-RPC 2.0 notification to server.\n * @method\n * @param {String} method - RPC method name\n * @param {Object} params - optional method parameters\n * @return {Promise}\n */\n notify(method: string, params?: IWSRequestParams)\n {\n return new Promise((resolve, reject) =>\n {\n if (!this.ready) return reject(new Error(\"socket not ready\"))\n\n const message = {\n jsonrpc: \"2.0\",\n method: method,\n params,\n }\n\n this.socket.send(this.dataPack.encode(message), (error) =>\n {\n if (error) return reject(error)\n\n resolve()\n })\n })\n }\n\n /**\n * Subscribes for a defined event.\n * @method\n * @param {String|Array} event - event name\n * @return {Undefined}\n * @throws {Error}\n */\n async subscribe(event: string | Array)\n {\n if (typeof event === \"string\") event = [event]\n\n const result = await this.call(\"rpc.on\", event)\n\n if (typeof event === \"string\" && result[event] !== \"ok\")\n throw new Error(\n \"Failed subscribing to an event '\" + event + \"' with: \" + result[event]\n )\n\n return result\n }\n\n /**\n * Unsubscribes from a defined event.\n * @method\n * @param {String|Array} event - event name\n * @return {Undefined}\n * @throws {Error}\n */\n async unsubscribe(event: string | Array)\n {\n if (typeof event === \"string\") event = [event]\n\n const result = await this.call(\"rpc.off\", event)\n\n if (typeof event === \"string\" && result[event] !== \"ok\")\n throw new Error(\"Failed unsubscribing from an event with: \" + result)\n\n return result\n }\n\n /**\n * Closes a WebSocket connection gracefully.\n * @method\n * @param {Number} code - socket close code\n * @param {String} data - optional data to be sent before closing\n * @return {Undefined}\n */\n close(code?: number, data?: string)\n {\n this.socket.close(code || 1000, data)\n }\n\n /**\n * Enable / disable automatic reconnection.\n * @method\n * @param {Boolean} reconnect - enable / disable reconnection\n * @return {Undefined}\n */\n setAutoReconnect(reconnect: boolean)\n {\n this.reconnect = reconnect\n }\n\n /**\n * Set the interval between reconnection attempts.\n * @method\n * @param {Number} interval - reconnection interval in milliseconds\n * @return {Undefined}\n */\n setReconnectInterval(interval: number)\n {\n this.reconnect_interval = interval\n }\n\n /**\n * Set the maximum number of reconnection attempts.\n * @method\n * @param {Number} max_reconnects - maximum reconnection attempts\n * @return {Undefined}\n */\n setMaxReconnects(max_reconnects: number)\n {\n this.max_reconnects = max_reconnects\n }\n\n /**\n * Connection/Message handler.\n * @method\n * @private\n * @param {String} address - WebSocket API address\n * @param {Object} options - ws options object\n * @return {Undefined}\n */\n private _connect(\n address: string,\n options: IWSClientAdditionalOptions & NodeWebSocket.ClientOptions\n )\n {\n clearTimeout(this.reconnect_timer_id)\n this.socket = this.webSocketFactory(address, options)\n\n this.socket.addEventListener(\"open\", () =>\n {\n this.ready = true\n this.emit(\"open\")\n this.current_reconnects = 0\n })\n\n this.socket.addEventListener(\"message\", ({ data: message }) =>\n {\n if (message instanceof ArrayBuffer)\n message = Buffer.from(message).toString()\n\n try\n {\n message = this.dataPack.decode(message)\n }\n catch (error)\n {\n return\n }\n\n // check if any listeners are attached and forward event\n if (message.notification && this.listeners(message.notification).length)\n {\n if (!Object.keys(message.params).length)\n return this.emit(message.notification)\n\n const args = [message.notification]\n\n if (message.params.constructor === Object) args.push(message.params)\n // using for-loop instead of unshift/spread because performance is better\n else\n for (let i = 0; i < message.params.length; i++)\n args.push(message.params[i])\n\n // run as microtask so that pending queue messages are resolved first\n // eslint-disable-next-line prefer-spread\n return Promise.resolve().then(() =>\n {\n // eslint-disable-next-line prefer-spread\n this.emit.apply(this, args)\n })\n }\n\n if (!this.queue[message.id])\n {\n // general JSON RPC 2.0 events\n if (message.method)\n {\n // run as microtask so that pending queue messages are resolved first\n return Promise.resolve().then(() =>\n {\n this.emit(message.method, message?.params)\n })\n }\n\n return\n }\n\n // reject early since server's response is invalid\n if (\"error\" in message === \"result\" in message)\n this.queue[message.id].promise[1](\n new Error(\n \"Server response malformed. Response must include either \\\"result\\\"\" +\n \" or \\\"error\\\", but not both.\"\n )\n )\n\n if (this.queue[message.id].timeout)\n clearTimeout(this.queue[message.id].timeout)\n\n if (message.error) this.queue[message.id].promise[1](message.error)\n else this.queue[message.id].promise[0](message.result)\n\n delete this.queue[message.id]\n })\n\n this.socket.addEventListener(\"error\", (error) => this.emit(\"error\", error))\n\n this.socket.addEventListener(\"close\", ({ code, reason }) =>\n {\n if (this.ready)\n // Delay close event until internal state is updated\n setTimeout(() => this.emit(\"close\", code, reason), 0)\n\n this.ready = false\n this.socket = undefined\n\n if (code === 1000) return\n\n this.current_reconnects++\n\n if (\n this.reconnect &&\n (this.max_reconnects > this.current_reconnects ||\n this.max_reconnects === 0)\n )\n this.reconnect_timer_id = setTimeout(\n () => this._connect(address, options),\n this.reconnect_interval\n )\n })\n }\n}\n","\"use strict\"\n\nexport interface DataPack<\n T,\n R extends string | ArrayBufferLike | Blob | ArrayBufferView\n> {\n encode(value: T): R;\n decode(value: R): T;\n}\n\nexport class DefaultDataPack implements DataPack\n{\n encode(value: Object): string\n {\n return JSON.stringify(value)\n }\n\n decode(value: string): Object\n {\n return JSON.parse(value)\n }\n}\n","\"use strict\"\n\nimport { WebSocket } from \"./lib/client/websocket.browser.js\"\nimport { CommonClient } from \"./lib/client.js\"\nimport { IWSClientAdditionalOptions } from \"./lib/client/client.types.js\"\n\nexport class Client extends CommonClient\n{\n constructor(\n address = \"ws://localhost:8080\",\n {\n autoconnect = true,\n reconnect = true,\n reconnect_interval = 1000,\n max_reconnects = 5,\n }: IWSClientAdditionalOptions = {},\n generate_request_id?: (\n method: string,\n params: object | Array\n ) => number\n )\n {\n super(\n WebSocket,\n address,\n {\n autoconnect,\n reconnect,\n reconnect_interval,\n max_reconnects,\n },\n generate_request_id\n )\n }\n}\n\nexport * from \"./lib/client.js\"\nexport * from \"./lib/client/websocket.browser.js\"\nexport * from \"./lib/client/client.types.js\"\nexport * from \"./lib/utils.js\"\n"]} \ No newline at end of file diff --git a/dist/index.browser.d.cts b/dist/index.browser.d.cts deleted file mode 100644 index 79aef30..0000000 --- a/dist/index.browser.d.cts +++ /dev/null @@ -1,5 +0,0 @@ -import CommonClient from "./lib/client.cjs"; -import { IWSClientAdditionalOptions } from "./lib/client/client.types.cjs"; -export declare class Client extends CommonClient { - constructor(address?: string, { autoconnect, reconnect, reconnect_interval, max_reconnects }?: IWSClientAdditionalOptions, generate_request_id?: (method: string, params: object | Array) => number); -} diff --git a/dist/index.browser.d.mts b/dist/index.browser.d.mts new file mode 100644 index 0000000..ae9a3ca --- /dev/null +++ b/dist/index.browser.d.mts @@ -0,0 +1,225 @@ +import { EventEmitter } from 'eventemitter3'; +import NodeWebSocket from 'ws'; + +type BrowserWebSocketType = InstanceType; +type NodeWebSocketType = InstanceType; +type NodeWebSocketTypeOptions = NodeWebSocket.ClientOptions; +interface IWSClientAdditionalOptions { + autoconnect?: boolean; + reconnect?: boolean; + reconnect_interval?: number; + max_reconnects?: number; +} +interface ICommonWebSocketFactory { + (address: string, options: IWSClientAdditionalOptions): ICommonWebSocket; +} +interface ICommonWebSocket { + send: (data: Parameters[0], optionsOrCallback: ((error?: Error) => void) | Parameters[1], callback?: (error?: Error) => void) => void; + close: (code?: number, reason?: string) => void; + addEventListener(type: K, listener: (ev: WebSocketEventMap[K]) => any, options?: boolean | AddEventListenerOptions): void; +} + +interface DataPack { + encode(value: T): R; + decode(value: R): T; +} +declare class DefaultDataPack implements DataPack { + encode(value: Object): string; + decode(value: string): Object; +} + +/** + * "Client" wraps "ws" or a browser-implemented "WebSocket" library + * according to the environment providing JSON RPC 2.0 support on top. + * @module Client + */ + +interface IQueueElement { + promise: [ + Parameters[0]>[0], + Parameters[0]>[1] + ]; + timeout?: ReturnType; +} +interface IQueue { + [x: number]: IQueueElement; +} +interface IWSRequestParams { + [x: string]: any; + [x: number]: any; +} +declare class CommonClient extends EventEmitter { + private address; + private rpc_id; + private queue; + private options; + private autoconnect; + private ready; + private reconnect; + private reconnect_timer_id; + private reconnect_interval; + private max_reconnects; + private rest_options; + private current_reconnects; + private generate_request_id; + private socket; + private webSocketFactory; + private dataPack; + /** + * Instantiate a Client class. + * @constructor + * @param {webSocketFactory} webSocketFactory - factory method for WebSocket + * @param {String} address - url to a websocket server + * @param {Object} options - ws options object with reconnect parameters + * @param {Function} generate_request_id - custom generation request Id + * @param {DataPack} dataPack - data pack contains encoder and decoder + * @return {CommonClient} + */ + constructor(webSocketFactory: ICommonWebSocketFactory, address?: string, { autoconnect, reconnect, reconnect_interval, max_reconnects, ...rest_options }?: { + autoconnect?: boolean; + reconnect?: boolean; + reconnect_interval?: number; + max_reconnects?: number; + }, generate_request_id?: (method: string, params: object | Array) => number, dataPack?: DataPack); + /** + * Connects to a defined server if not connected already. + * @method + * @return {Undefined} + */ + connect(): void; + /** + * Calls a registered RPC method on server. + * @method + * @param {String} method - RPC method name + * @param {Object|Array} params - optional method parameters + * @param {Number} timeout - RPC reply timeout value + * @param {Object} ws_opts - options passed to ws + * @return {Promise} + */ + call(method: string, params?: IWSRequestParams, timeout?: number, ws_opts?: Parameters[1]): Promise; + /** + * Logins with the other side of the connection. + * @method + * @param {Object} params - Login credentials object + * @return {Promise} + */ + login(params: IWSRequestParams): Promise; + /** + * Fetches a list of client's methods registered on server. + * @method + * @return {Array} + */ + listMethods(): Promise; + /** + * Sends a JSON-RPC 2.0 notification to server. + * @method + * @param {String} method - RPC method name + * @param {Object} params - optional method parameters + * @return {Promise} + */ + notify(method: string, params?: IWSRequestParams): Promise; + /** + * Subscribes for a defined event. + * @method + * @param {String|Array} event - event name + * @return {Undefined} + * @throws {Error} + */ + subscribe(event: string | Array): Promise; + /** + * Unsubscribes from a defined event. + * @method + * @param {String|Array} event - event name + * @return {Undefined} + * @throws {Error} + */ + unsubscribe(event: string | Array): Promise; + /** + * Closes a WebSocket connection gracefully. + * @method + * @param {Number} code - socket close code + * @param {String} data - optional data to be sent before closing + * @return {Undefined} + */ + close(code?: number, data?: string): void; + /** + * Enable / disable automatic reconnection. + * @method + * @param {Boolean} reconnect - enable / disable reconnection + * @return {Undefined} + */ + setAutoReconnect(reconnect: boolean): void; + /** + * Set the interval between reconnection attempts. + * @method + * @param {Number} interval - reconnection interval in milliseconds + * @return {Undefined} + */ + setReconnectInterval(interval: number): void; + /** + * Set the maximum number of reconnection attempts. + * @method + * @param {Number} max_reconnects - maximum reconnection attempts + * @return {Undefined} + */ + setMaxReconnects(max_reconnects: number): void; + /** + * Connection/Message handler. + * @method + * @private + * @param {String} address - WebSocket API address + * @param {Object} options - ws options object + * @return {Undefined} + */ + private _connect; +} + +/** + * WebSocket implements a browser-side WebSocket specification. + * @module Client + */ + +declare class WebSocketBrowserImpl extends EventEmitter { + socket: BrowserWebSocketType; + /** Instantiate a WebSocket class + * @constructor + * @param {String} address - url to a websocket server + * @param {(Object)} options - websocket options + * @param {(String|Array)} protocols - a list of protocols + * @return {WebSocketBrowserImpl} - returns a WebSocket instance + */ + constructor(address: string, options: {}, protocols?: string | string[]); + /** + * Sends data through a websocket connection + * @method + * @param {(String|Object)} data - data to be sent via websocket + * @param {Object} optionsOrCallback - ws options + * @param {Function} callback - a callback called once the data is sent + * @return {Undefined} + */ + send(data: Parameters[0], optionsOrCallback: (error?: Error) => void | Parameters[1], callback?: () => void): void; + /** + * Closes an underlying socket + * @method + * @param {Number} code - status code explaining why the connection is being closed + * @param {String} reason - a description why the connection is closing + * @return {Undefined} + * @throws {Error} + */ + close(code?: number, reason?: string): void; + addEventListener(type: K, listener: (ev: WebSocketEventMap[K]) => any, options?: boolean | AddEventListenerOptions): void; +} +/** + * factory method for common WebSocket instance + * @method + * @param {String} address - url to a websocket server + * @param {(Object)} options - websocket options + * @return {Undefined} + */ +declare function WebSocket$1(address: string, options: IWSClientAdditionalOptions): WebSocketBrowserImpl; + +declare class Client extends CommonClient { + constructor(address?: string, { autoconnect, reconnect, reconnect_interval, max_reconnects, }?: IWSClientAdditionalOptions, generate_request_id?: (method: string, params: object | Array) => number); +} + +export { type BrowserWebSocketType, Client, CommonClient, type DataPack, DefaultDataPack, type ICommonWebSocket, type ICommonWebSocketFactory, type IQueue, type IWSClientAdditionalOptions, type IWSRequestParams, type NodeWebSocketType, type NodeWebSocketTypeOptions, WebSocket$1 as WebSocket }; diff --git a/dist/index.browser.d.ts b/dist/index.browser.d.ts new file mode 100644 index 0000000..ae9a3ca --- /dev/null +++ b/dist/index.browser.d.ts @@ -0,0 +1,225 @@ +import { EventEmitter } from 'eventemitter3'; +import NodeWebSocket from 'ws'; + +type BrowserWebSocketType = InstanceType; +type NodeWebSocketType = InstanceType; +type NodeWebSocketTypeOptions = NodeWebSocket.ClientOptions; +interface IWSClientAdditionalOptions { + autoconnect?: boolean; + reconnect?: boolean; + reconnect_interval?: number; + max_reconnects?: number; +} +interface ICommonWebSocketFactory { + (address: string, options: IWSClientAdditionalOptions): ICommonWebSocket; +} +interface ICommonWebSocket { + send: (data: Parameters[0], optionsOrCallback: ((error?: Error) => void) | Parameters[1], callback?: (error?: Error) => void) => void; + close: (code?: number, reason?: string) => void; + addEventListener(type: K, listener: (ev: WebSocketEventMap[K]) => any, options?: boolean | AddEventListenerOptions): void; +} + +interface DataPack { + encode(value: T): R; + decode(value: R): T; +} +declare class DefaultDataPack implements DataPack { + encode(value: Object): string; + decode(value: string): Object; +} + +/** + * "Client" wraps "ws" or a browser-implemented "WebSocket" library + * according to the environment providing JSON RPC 2.0 support on top. + * @module Client + */ + +interface IQueueElement { + promise: [ + Parameters[0]>[0], + Parameters[0]>[1] + ]; + timeout?: ReturnType; +} +interface IQueue { + [x: number]: IQueueElement; +} +interface IWSRequestParams { + [x: string]: any; + [x: number]: any; +} +declare class CommonClient extends EventEmitter { + private address; + private rpc_id; + private queue; + private options; + private autoconnect; + private ready; + private reconnect; + private reconnect_timer_id; + private reconnect_interval; + private max_reconnects; + private rest_options; + private current_reconnects; + private generate_request_id; + private socket; + private webSocketFactory; + private dataPack; + /** + * Instantiate a Client class. + * @constructor + * @param {webSocketFactory} webSocketFactory - factory method for WebSocket + * @param {String} address - url to a websocket server + * @param {Object} options - ws options object with reconnect parameters + * @param {Function} generate_request_id - custom generation request Id + * @param {DataPack} dataPack - data pack contains encoder and decoder + * @return {CommonClient} + */ + constructor(webSocketFactory: ICommonWebSocketFactory, address?: string, { autoconnect, reconnect, reconnect_interval, max_reconnects, ...rest_options }?: { + autoconnect?: boolean; + reconnect?: boolean; + reconnect_interval?: number; + max_reconnects?: number; + }, generate_request_id?: (method: string, params: object | Array) => number, dataPack?: DataPack); + /** + * Connects to a defined server if not connected already. + * @method + * @return {Undefined} + */ + connect(): void; + /** + * Calls a registered RPC method on server. + * @method + * @param {String} method - RPC method name + * @param {Object|Array} params - optional method parameters + * @param {Number} timeout - RPC reply timeout value + * @param {Object} ws_opts - options passed to ws + * @return {Promise} + */ + call(method: string, params?: IWSRequestParams, timeout?: number, ws_opts?: Parameters[1]): Promise; + /** + * Logins with the other side of the connection. + * @method + * @param {Object} params - Login credentials object + * @return {Promise} + */ + login(params: IWSRequestParams): Promise; + /** + * Fetches a list of client's methods registered on server. + * @method + * @return {Array} + */ + listMethods(): Promise; + /** + * Sends a JSON-RPC 2.0 notification to server. + * @method + * @param {String} method - RPC method name + * @param {Object} params - optional method parameters + * @return {Promise} + */ + notify(method: string, params?: IWSRequestParams): Promise; + /** + * Subscribes for a defined event. + * @method + * @param {String|Array} event - event name + * @return {Undefined} + * @throws {Error} + */ + subscribe(event: string | Array): Promise; + /** + * Unsubscribes from a defined event. + * @method + * @param {String|Array} event - event name + * @return {Undefined} + * @throws {Error} + */ + unsubscribe(event: string | Array): Promise; + /** + * Closes a WebSocket connection gracefully. + * @method + * @param {Number} code - socket close code + * @param {String} data - optional data to be sent before closing + * @return {Undefined} + */ + close(code?: number, data?: string): void; + /** + * Enable / disable automatic reconnection. + * @method + * @param {Boolean} reconnect - enable / disable reconnection + * @return {Undefined} + */ + setAutoReconnect(reconnect: boolean): void; + /** + * Set the interval between reconnection attempts. + * @method + * @param {Number} interval - reconnection interval in milliseconds + * @return {Undefined} + */ + setReconnectInterval(interval: number): void; + /** + * Set the maximum number of reconnection attempts. + * @method + * @param {Number} max_reconnects - maximum reconnection attempts + * @return {Undefined} + */ + setMaxReconnects(max_reconnects: number): void; + /** + * Connection/Message handler. + * @method + * @private + * @param {String} address - WebSocket API address + * @param {Object} options - ws options object + * @return {Undefined} + */ + private _connect; +} + +/** + * WebSocket implements a browser-side WebSocket specification. + * @module Client + */ + +declare class WebSocketBrowserImpl extends EventEmitter { + socket: BrowserWebSocketType; + /** Instantiate a WebSocket class + * @constructor + * @param {String} address - url to a websocket server + * @param {(Object)} options - websocket options + * @param {(String|Array)} protocols - a list of protocols + * @return {WebSocketBrowserImpl} - returns a WebSocket instance + */ + constructor(address: string, options: {}, protocols?: string | string[]); + /** + * Sends data through a websocket connection + * @method + * @param {(String|Object)} data - data to be sent via websocket + * @param {Object} optionsOrCallback - ws options + * @param {Function} callback - a callback called once the data is sent + * @return {Undefined} + */ + send(data: Parameters[0], optionsOrCallback: (error?: Error) => void | Parameters[1], callback?: () => void): void; + /** + * Closes an underlying socket + * @method + * @param {Number} code - status code explaining why the connection is being closed + * @param {String} reason - a description why the connection is closing + * @return {Undefined} + * @throws {Error} + */ + close(code?: number, reason?: string): void; + addEventListener(type: K, listener: (ev: WebSocketEventMap[K]) => any, options?: boolean | AddEventListenerOptions): void; +} +/** + * factory method for common WebSocket instance + * @method + * @param {String} address - url to a websocket server + * @param {(Object)} options - websocket options + * @return {Undefined} + */ +declare function WebSocket$1(address: string, options: IWSClientAdditionalOptions): WebSocketBrowserImpl; + +declare class Client extends CommonClient { + constructor(address?: string, { autoconnect, reconnect, reconnect_interval, max_reconnects, }?: IWSClientAdditionalOptions, generate_request_id?: (method: string, params: object | Array) => number); +} + +export { type BrowserWebSocketType, Client, CommonClient, type DataPack, DefaultDataPack, type ICommonWebSocket, type ICommonWebSocketFactory, type IQueue, type IWSClientAdditionalOptions, type IWSRequestParams, type NodeWebSocketType, type NodeWebSocketTypeOptions, WebSocket$1 as WebSocket }; diff --git a/dist/index.browser.mjs b/dist/index.browser.mjs new file mode 100644 index 0000000..1674310 --- /dev/null +++ b/dist/index.browser.mjs @@ -0,0 +1,384 @@ +import { Buffer } from 'buffer'; +import { EventEmitter } from 'eventemitter3'; + +// node_modules/esbuild-plugin-polyfill-node/polyfills/buffer.js +var WebSocketBrowserImpl = class extends EventEmitter { + socket; + /** Instantiate a WebSocket class + * @constructor + * @param {String} address - url to a websocket server + * @param {(Object)} options - websocket options + * @param {(String|Array)} protocols - a list of protocols + * @return {WebSocketBrowserImpl} - returns a WebSocket instance + */ + constructor(address, options, protocols) { + super(); + this.socket = new window.WebSocket(address, protocols); + this.socket.onopen = () => this.emit("open"); + this.socket.onmessage = (event) => this.emit("message", event.data); + this.socket.onerror = (error) => this.emit("error", error); + this.socket.onclose = (event) => { + this.emit("close", event.code, event.reason); + }; + } + /** + * Sends data through a websocket connection + * @method + * @param {(String|Object)} data - data to be sent via websocket + * @param {Object} optionsOrCallback - ws options + * @param {Function} callback - a callback called once the data is sent + * @return {Undefined} + */ + send(data, optionsOrCallback, callback) { + const cb = callback || optionsOrCallback; + try { + this.socket.send(data); + cb(); + } catch (error) { + cb(error); + } + } + /** + * Closes an underlying socket + * @method + * @param {Number} code - status code explaining why the connection is being closed + * @param {String} reason - a description why the connection is closing + * @return {Undefined} + * @throws {Error} + */ + close(code, reason) { + this.socket.close(code, reason); + } + addEventListener(type, listener, options) { + this.socket.addEventListener(type, listener, options); + } +}; +function WebSocket(address, options) { + return new WebSocketBrowserImpl(address, options); +} + +// src/lib/utils.ts +var DefaultDataPack = class { + encode(value) { + return JSON.stringify(value); + } + decode(value) { + return JSON.parse(value); + } +}; + +// src/lib/client.ts +var CommonClient = class extends EventEmitter { + address; + rpc_id; + queue; + options; + autoconnect; + ready; + reconnect; + reconnect_timer_id; + reconnect_interval; + max_reconnects; + rest_options; + current_reconnects; + generate_request_id; + socket; + webSocketFactory; + dataPack; + /** + * Instantiate a Client class. + * @constructor + * @param {webSocketFactory} webSocketFactory - factory method for WebSocket + * @param {String} address - url to a websocket server + * @param {Object} options - ws options object with reconnect parameters + * @param {Function} generate_request_id - custom generation request Id + * @param {DataPack} dataPack - data pack contains encoder and decoder + * @return {CommonClient} + */ + constructor(webSocketFactory, address = "ws://localhost:8080", { + autoconnect = true, + reconnect = true, + reconnect_interval = 1e3, + max_reconnects = 5, + ...rest_options + } = {}, generate_request_id, dataPack) { + super(); + this.webSocketFactory = webSocketFactory; + this.queue = {}; + this.rpc_id = 0; + this.address = address; + this.autoconnect = autoconnect; + this.ready = false; + this.reconnect = reconnect; + this.reconnect_timer_id = void 0; + this.reconnect_interval = reconnect_interval; + this.max_reconnects = max_reconnects; + this.rest_options = rest_options; + this.current_reconnects = 0; + this.generate_request_id = generate_request_id || (() => ++this.rpc_id); + if (!dataPack) this.dataPack = new DefaultDataPack(); + else this.dataPack = dataPack; + if (this.autoconnect) + this._connect(this.address, { + autoconnect: this.autoconnect, + reconnect: this.reconnect, + reconnect_interval: this.reconnect_interval, + max_reconnects: this.max_reconnects, + ...this.rest_options + }); + } + /** + * Connects to a defined server if not connected already. + * @method + * @return {Undefined} + */ + connect() { + if (this.socket) return; + this._connect(this.address, { + autoconnect: this.autoconnect, + reconnect: this.reconnect, + reconnect_interval: this.reconnect_interval, + max_reconnects: this.max_reconnects, + ...this.rest_options + }); + } + /** + * Calls a registered RPC method on server. + * @method + * @param {String} method - RPC method name + * @param {Object|Array} params - optional method parameters + * @param {Number} timeout - RPC reply timeout value + * @param {Object} ws_opts - options passed to ws + * @return {Promise} + */ + call(method, params, timeout, ws_opts) { + if (!ws_opts && "object" === typeof timeout) { + ws_opts = timeout; + timeout = null; + } + return new Promise((resolve, reject) => { + if (!this.ready) return reject(new Error("socket not ready")); + const rpc_id = this.generate_request_id(method, params); + const message = { + jsonrpc: "2.0", + method, + params: params || void 0, + id: rpc_id + }; + this.socket.send(this.dataPack.encode(message), ws_opts, (error) => { + if (error) return reject(error); + this.queue[rpc_id] = { promise: [resolve, reject] }; + if (timeout) { + this.queue[rpc_id].timeout = setTimeout(() => { + delete this.queue[rpc_id]; + reject(new Error("reply timeout")); + }, timeout); + } + }); + }); + } + /** + * Logins with the other side of the connection. + * @method + * @param {Object} params - Login credentials object + * @return {Promise} + */ + async login(params) { + const resp = await this.call("rpc.login", params); + if (!resp) throw new Error("authentication failed"); + return resp; + } + /** + * Fetches a list of client's methods registered on server. + * @method + * @return {Array} + */ + async listMethods() { + return await this.call("__listMethods"); + } + /** + * Sends a JSON-RPC 2.0 notification to server. + * @method + * @param {String} method - RPC method name + * @param {Object} params - optional method parameters + * @return {Promise} + */ + notify(method, params) { + return new Promise((resolve, reject) => { + if (!this.ready) return reject(new Error("socket not ready")); + const message = { + jsonrpc: "2.0", + method, + params + }; + this.socket.send(this.dataPack.encode(message), (error) => { + if (error) return reject(error); + resolve(); + }); + }); + } + /** + * Subscribes for a defined event. + * @method + * @param {String|Array} event - event name + * @return {Undefined} + * @throws {Error} + */ + async subscribe(event) { + if (typeof event === "string") event = [event]; + const result = await this.call("rpc.on", event); + if (typeof event === "string" && result[event] !== "ok") + throw new Error( + "Failed subscribing to an event '" + event + "' with: " + result[event] + ); + return result; + } + /** + * Unsubscribes from a defined event. + * @method + * @param {String|Array} event - event name + * @return {Undefined} + * @throws {Error} + */ + async unsubscribe(event) { + if (typeof event === "string") event = [event]; + const result = await this.call("rpc.off", event); + if (typeof event === "string" && result[event] !== "ok") + throw new Error("Failed unsubscribing from an event with: " + result); + return result; + } + /** + * Closes a WebSocket connection gracefully. + * @method + * @param {Number} code - socket close code + * @param {String} data - optional data to be sent before closing + * @return {Undefined} + */ + close(code, data) { + this.socket.close(code || 1e3, data); + } + /** + * Enable / disable automatic reconnection. + * @method + * @param {Boolean} reconnect - enable / disable reconnection + * @return {Undefined} + */ + setAutoReconnect(reconnect) { + this.reconnect = reconnect; + } + /** + * Set the interval between reconnection attempts. + * @method + * @param {Number} interval - reconnection interval in milliseconds + * @return {Undefined} + */ + setReconnectInterval(interval) { + this.reconnect_interval = interval; + } + /** + * Set the maximum number of reconnection attempts. + * @method + * @param {Number} max_reconnects - maximum reconnection attempts + * @return {Undefined} + */ + setMaxReconnects(max_reconnects) { + this.max_reconnects = max_reconnects; + } + /** + * Connection/Message handler. + * @method + * @private + * @param {String} address - WebSocket API address + * @param {Object} options - ws options object + * @return {Undefined} + */ + _connect(address, options) { + clearTimeout(this.reconnect_timer_id); + this.socket = this.webSocketFactory(address, options); + this.socket.addEventListener("open", () => { + this.ready = true; + this.emit("open"); + this.current_reconnects = 0; + }); + this.socket.addEventListener("message", ({ data: message }) => { + if (message instanceof ArrayBuffer) + message = Buffer.from(message).toString(); + try { + message = this.dataPack.decode(message); + } catch (error) { + return; + } + if (message.notification && this.listeners(message.notification).length) { + if (!Object.keys(message.params).length) + return this.emit(message.notification); + const args = [message.notification]; + if (message.params.constructor === Object) args.push(message.params); + else + for (let i = 0; i < message.params.length; i++) + args.push(message.params[i]); + return Promise.resolve().then(() => { + this.emit.apply(this, args); + }); + } + if (!this.queue[message.id]) { + if (message.method) { + return Promise.resolve().then(() => { + this.emit(message.method, message?.params); + }); + } + return; + } + if ("error" in message === "result" in message) + this.queue[message.id].promise[1]( + new Error( + 'Server response malformed. Response must include either "result" or "error", but not both.' + ) + ); + if (this.queue[message.id].timeout) + clearTimeout(this.queue[message.id].timeout); + if (message.error) this.queue[message.id].promise[1](message.error); + else this.queue[message.id].promise[0](message.result); + delete this.queue[message.id]; + }); + this.socket.addEventListener("error", (error) => this.emit("error", error)); + this.socket.addEventListener("close", ({ code, reason }) => { + if (this.ready) + setTimeout(() => this.emit("close", code, reason), 0); + this.ready = false; + this.socket = void 0; + if (code === 1e3) return; + this.current_reconnects++; + if (this.reconnect && (this.max_reconnects > this.current_reconnects || this.max_reconnects === 0)) + this.reconnect_timer_id = setTimeout( + () => this._connect(address, options), + this.reconnect_interval + ); + }); + } +}; + +// src/index.browser.ts +var Client = class extends CommonClient { + constructor(address = "ws://localhost:8080", { + autoconnect = true, + reconnect = true, + reconnect_interval = 1e3, + max_reconnects = 5 + } = {}, generate_request_id) { + super( + WebSocket, + address, + { + autoconnect, + reconnect, + reconnect_interval, + max_reconnects + }, + generate_request_id + ); + } +}; + +export { Client, CommonClient, DefaultDataPack, WebSocket }; +//# sourceMappingURL=out.js.map +//# sourceMappingURL=index.browser.mjs.map \ No newline at end of file diff --git a/dist/index.browser.mjs.map b/dist/index.browser.mjs.map new file mode 100644 index 0000000..d720c5f --- /dev/null +++ b/dist/index.browser.mjs.map @@ -0,0 +1 @@ +{"version":3,"sources":["../node_modules/esbuild-plugin-polyfill-node/polyfills/buffer.js","../src/lib/client/websocket.browser.ts","../src/lib/client.ts","../src/lib/utils.ts","../src/index.browser.ts"],"names":["EventEmitter"],"mappings":";AAAA,SAAS,cAAc;;;ACOvB,SAAS,oBAAoB;AAQ7B,IAAM,uBAAN,cAAmC,aACnC;AAAA,EACI;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,YAAY,SAAiB,SAAa,WAC1C;AACI,UAAM;AAEN,SAAK,SAAS,IAAI,OAAO,UAAU,SAAS,SAAS;AAErD,SAAK,OAAO,SAAS,MAAM,KAAK,KAAK,MAAM;AAC3C,SAAK,OAAO,YAAY,CAAC,UAAU,KAAK,KAAK,WAAW,MAAM,IAAI;AAClE,SAAK,OAAO,UAAU,CAAC,UAAU,KAAK,KAAK,SAAS,KAAK;AACzD,SAAK,OAAO,UAAU,CAAC,UACvB;AACI,WAAK,KAAK,SAAS,MAAM,MAAM,MAAM,MAAM;AAAA,IAC/C;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,KACI,MACA,mBAGA,UAEJ;AACI,UAAM,KAAK,YAAY;AAEvB,QACA;AACI,WAAK,OAAO,KAAK,IAAI;AACrB,SAAG;AAAA,IACP,SACO,OACP;AACI,SAAG,KAAK;AAAA,IACZ;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,MAAM,MAAe,QACrB;AACI,SAAK,OAAO,MAAM,MAAM,MAAM;AAAA,EAClC;AAAA,EAEA,iBACI,MACA,UACA,SAEJ;AACI,SAAK,OAAO,iBAAiB,MAAM,UAAU,OAAO;AAAA,EACxD;AACJ;AASO,SAAS,UACZ,SACA,SAEJ;AACI,SAAO,IAAI,qBAAqB,SAAS,OAAO;AACpD;;;ACjGA,SAAS,gBAAAA,qBAAoB;;;ACCtB,IAAM,kBAAN,MACP;AAAA,EACI,OAAO,OACP;AACI,WAAO,KAAK,UAAU,KAAK;AAAA,EAC/B;AAAA,EAEA,OAAO,OACP;AACI,WAAO,KAAK,MAAM,KAAK;AAAA,EAC3B;AACJ;;;ADeO,IAAM,eAAN,cAA2BA,cAClC;AAAA,EACY;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAEA;AAAA,EACA;AAAA,EAIA;AAAA,EACA;AAAA,EACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYR,YACI,kBACA,UAAU,uBACV;AAAA,IACI,cAAc;AAAA,IACd,YAAY;AAAA,IACZ,qBAAqB;AAAA,IACrB,iBAAiB;AAAA,IACjB,GAAG;AAAA,EACP,IAAI,CAAC,GACL,qBAIA,UAEJ;AACI,UAAM;AAEN,SAAK,mBAAmB;AAExB,SAAK,QAAQ,CAAC;AACd,SAAK,SAAS;AAEd,SAAK,UAAU;AACf,SAAK,cAAc;AACnB,SAAK,QAAQ;AACb,SAAK,YAAY;AACjB,SAAK,qBAAqB;AAC1B,SAAK,qBAAqB;AAC1B,SAAK,iBAAiB;AACtB,SAAK,eAAe;AACpB,SAAK,qBAAqB;AAC1B,SAAK,sBAAsB,wBAAwB,MAAM,EAAE,KAAK;AAEhE,QAAI,CAAC,SAAU,MAAK,WAAW,IAAI,gBAAgB;AAAA,QAC9C,MAAK,WAAW;AAErB,QAAI,KAAK;AACL,WAAK,SAAS,KAAK,SAAS;AAAA,QACxB,aAAa,KAAK;AAAA,QAClB,WAAW,KAAK;AAAA,QAChB,oBAAoB,KAAK;AAAA,QACzB,gBAAgB,KAAK;AAAA,QACrB,GAAG,KAAK;AAAA,MACZ,CAAC;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,UACA;AACI,QAAI,KAAK,OAAQ;AAEjB,SAAK,SAAS,KAAK,SAAS;AAAA,MACxB,aAAa,KAAK;AAAA,MAClB,WAAW,KAAK;AAAA,MAChB,oBAAoB,KAAK;AAAA,MACzB,gBAAgB,KAAK;AAAA,MACrB,GAAG,KAAK;AAAA,IACZ,CAAC;AAAA,EACL;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,KACI,QACA,QACA,SACA,SAEJ;AACI,QAAI,CAAC,WAAW,aAAa,OAAO,SACpC;AACI,gBAAU;AACV,gBAAU;AAAA,IACd;AAEA,WAAO,IAAI,QAAQ,CAAC,SAAS,WAC7B;AACI,UAAI,CAAC,KAAK,MAAO,QAAO,OAAO,IAAI,MAAM,kBAAkB,CAAC;AAE5D,YAAM,SAAS,KAAK,oBAAoB,QAAQ,MAAM;AAEtD,YAAM,UAAU;AAAA,QACZ,SAAS;AAAA,QACT;AAAA,QACA,QAAQ,UAAU;AAAA,QAClB,IAAI;AAAA,MACR;AAEA,WAAK,OAAO,KAAK,KAAK,SAAS,OAAO,OAAO,GAAG,SAAS,CAAC,UAC1D;AACI,YAAI,MAAO,QAAO,OAAO,KAAK;AAE9B,aAAK,MAAM,MAAM,IAAI,EAAE,SAAS,CAAC,SAAS,MAAM,EAAE;AAElD,YAAI,SACJ;AACI,eAAK,MAAM,MAAM,EAAE,UAAU,WAAW,MACxC;AACI,mBAAO,KAAK,MAAM,MAAM;AACxB,mBAAO,IAAI,MAAM,eAAe,CAAC;AAAA,UACrC,GAAG,OAAO;AAAA,QACd;AAAA,MACJ,CAAC;AAAA,IACL,CAAC;AAAA,EACL;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,MAAM,QACZ;AACI,UAAM,OAAO,MAAM,KAAK,KAAK,aAAa,MAAM;AAEhD,QAAI,CAAC,KAAM,OAAM,IAAI,MAAM,uBAAuB;AAElD,WAAO;AAAA,EACX;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,cACN;AACI,WAAO,MAAM,KAAK,KAAK,eAAe;AAAA,EAC1C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,OAAO,QAAgB,QACvB;AACI,WAAO,IAAI,QAAc,CAAC,SAAS,WACnC;AACI,UAAI,CAAC,KAAK,MAAO,QAAO,OAAO,IAAI,MAAM,kBAAkB,CAAC;AAE5D,YAAM,UAAU;AAAA,QACZ,SAAS;AAAA,QACT;AAAA,QACA;AAAA,MACJ;AAEA,WAAK,OAAO,KAAK,KAAK,SAAS,OAAO,OAAO,GAAG,CAAC,UACjD;AACI,YAAI,MAAO,QAAO,OAAO,KAAK;AAE9B,gBAAQ;AAAA,MACZ,CAAC;AAAA,IACL,CAAC;AAAA,EACL;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,UAAU,OAChB;AACI,QAAI,OAAO,UAAU,SAAU,SAAQ,CAAC,KAAK;AAE7C,UAAM,SAAS,MAAM,KAAK,KAAK,UAAU,KAAK;AAE9C,QAAI,OAAO,UAAU,YAAY,OAAO,KAAK,MAAM;AAC/C,YAAM,IAAI;AAAA,QACN,qCAAqC,QAAQ,aAAa,OAAO,KAAK;AAAA,MAC1E;AAEJ,WAAO;AAAA,EACX;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,YAAY,OAClB;AACI,QAAI,OAAO,UAAU,SAAU,SAAQ,CAAC,KAAK;AAE7C,UAAM,SAAS,MAAM,KAAK,KAAK,WAAW,KAAK;AAE/C,QAAI,OAAO,UAAU,YAAY,OAAO,KAAK,MAAM;AAC/C,YAAM,IAAI,MAAM,8CAA8C,MAAM;AAExE,WAAO;AAAA,EACX;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,MAAe,MACrB;AACI,SAAK,OAAO,MAAM,QAAQ,KAAM,IAAI;AAAA,EACxC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,iBAAiB,WACjB;AACI,SAAK,YAAY;AAAA,EACrB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,qBAAqB,UACrB;AACI,SAAK,qBAAqB;AAAA,EAC9B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,iBAAiB,gBACjB;AACI,SAAK,iBAAiB;AAAA,EAC1B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUQ,SACJ,SACA,SAEJ;AACI,iBAAa,KAAK,kBAAkB;AACpC,SAAK,SAAS,KAAK,iBAAiB,SAAS,OAAO;AAEpD,SAAK,OAAO,iBAAiB,QAAQ,MACrC;AACI,WAAK,QAAQ;AACb,WAAK,KAAK,MAAM;AAChB,WAAK,qBAAqB;AAAA,IAC9B,CAAC;AAED,SAAK,OAAO,iBAAiB,WAAW,CAAC,EAAE,MAAM,QAAQ,MACzD;AACI,UAAI,mBAAmB;AACnB,kBAAU,OAAO,KAAK,OAAO,EAAE,SAAS;AAE5C,UACA;AACI,kBAAU,KAAK,SAAS,OAAO,OAAO;AAAA,MAC1C,SACO,OACP;AACI;AAAA,MACJ;AAGA,UAAI,QAAQ,gBAAgB,KAAK,UAAU,QAAQ,YAAY,EAAE,QACjE;AACI,YAAI,CAAC,OAAO,KAAK,QAAQ,MAAM,EAAE;AAC7B,iBAAO,KAAK,KAAK,QAAQ,YAAY;AAEzC,cAAM,OAAO,CAAC,QAAQ,YAAY;AAElC,YAAI,QAAQ,OAAO,gBAAgB,OAAQ,MAAK,KAAK,QAAQ,MAAM;AAAA;AAG/D,mBAAS,IAAI,GAAG,IAAI,QAAQ,OAAO,QAAQ;AACvC,iBAAK,KAAK,QAAQ,OAAO,CAAC,CAAC;AAInC,eAAO,QAAQ,QAAQ,EAAE,KAAK,MAC9B;AAEI,eAAK,KAAK,MAAM,MAAM,IAAI;AAAA,QAC9B,CAAC;AAAA,MACL;AAEA,UAAI,CAAC,KAAK,MAAM,QAAQ,EAAE,GAC1B;AAEI,YAAI,QAAQ,QACZ;AAEI,iBAAO,QAAQ,QAAQ,EAAE,KAAK,MAC9B;AACI,iBAAK,KAAK,QAAQ,QAAQ,SAAS,MAAM;AAAA,UAC7C,CAAC;AAAA,QACL;AAEA;AAAA,MACJ;AAGA,UAAI,WAAW,YAAY,YAAY;AACnC,aAAK,MAAM,QAAQ,EAAE,EAAE,QAAQ,CAAC;AAAA,UAC5B,IAAI;AAAA,YACA;AAAA,UAEJ;AAAA,QACJ;AAEJ,UAAI,KAAK,MAAM,QAAQ,EAAE,EAAE;AACvB,qBAAa,KAAK,MAAM,QAAQ,EAAE,EAAE,OAAO;AAE/C,UAAI,QAAQ,MAAO,MAAK,MAAM,QAAQ,EAAE,EAAE,QAAQ,CAAC,EAAE,QAAQ,KAAK;AAAA,UAC7D,MAAK,MAAM,QAAQ,EAAE,EAAE,QAAQ,CAAC,EAAE,QAAQ,MAAM;AAErD,aAAO,KAAK,MAAM,QAAQ,EAAE;AAAA,IAChC,CAAC;AAED,SAAK,OAAO,iBAAiB,SAAS,CAAC,UAAU,KAAK,KAAK,SAAS,KAAK,CAAC;AAE1E,SAAK,OAAO,iBAAiB,SAAS,CAAC,EAAE,MAAM,OAAO,MACtD;AACI,UAAI,KAAK;AAEL,mBAAW,MAAM,KAAK,KAAK,SAAS,MAAM,MAAM,GAAG,CAAC;AAExD,WAAK,QAAQ;AACb,WAAK,SAAS;AAEd,UAAI,SAAS,IAAM;AAEnB,WAAK;AAEL,UACI,KAAK,cACZ,KAAK,iBAAiB,KAAK,sBAC1B,KAAK,mBAAmB;AAElB,aAAK,qBAAqB;AAAA,UACtB,MAAM,KAAK,SAAS,SAAS,OAAO;AAAA,UACpC,KAAK;AAAA,QACT;AAAA,IACR,CAAC;AAAA,EACL;AACJ;;;AEvbO,IAAM,SAAN,cAAqB,aAC5B;AAAA,EACI,YACI,UAAU,uBACV;AAAA,IACI,cAAc;AAAA,IACd,YAAY;AAAA,IACZ,qBAAqB;AAAA,IACrB,iBAAiB;AAAA,EACrB,IAAgC,CAAC,GACjC,qBAKJ;AACI;AAAA,MACI;AAAA,MACA;AAAA,MACA;AAAA,QACI;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACJ;AAAA,MACA;AAAA,IACJ;AAAA,EACJ;AACJ","sourcesContent":["export { Buffer } from \"buffer\";\n","/**\n * WebSocket implements a browser-side WebSocket specification.\n * @module Client\n */\n\n\"use strict\"\n\nimport { EventEmitter } from \"eventemitter3\"\n\nimport {\n BrowserWebSocketType,\n NodeWebSocketType,\n IWSClientAdditionalOptions,\n} from \"./client.types.js\"\n\nclass WebSocketBrowserImpl extends EventEmitter\n{\n socket: BrowserWebSocketType\n\n /** Instantiate a WebSocket class\n * @constructor\n * @param {String} address - url to a websocket server\n * @param {(Object)} options - websocket options\n * @param {(String|Array)} protocols - a list of protocols\n * @return {WebSocketBrowserImpl} - returns a WebSocket instance\n */\n constructor(address: string, options: {}, protocols?: string | string[])\n {\n super()\n\n this.socket = new window.WebSocket(address, protocols)\n\n this.socket.onopen = () => this.emit(\"open\")\n this.socket.onmessage = (event) => this.emit(\"message\", event.data)\n this.socket.onerror = (error) => this.emit(\"error\", error)\n this.socket.onclose = (event) =>\n {\n this.emit(\"close\", event.code, event.reason)\n }\n }\n\n /**\n * Sends data through a websocket connection\n * @method\n * @param {(String|Object)} data - data to be sent via websocket\n * @param {Object} optionsOrCallback - ws options\n * @param {Function} callback - a callback called once the data is sent\n * @return {Undefined}\n */\n send(\n data: Parameters[0],\n optionsOrCallback: (\n error?: Error\n ) => void | Parameters[1],\n callback?: () => void\n )\n {\n const cb = callback || optionsOrCallback\n\n try\n {\n this.socket.send(data)\n cb()\n }\n catch (error)\n {\n cb(error)\n }\n }\n\n /**\n * Closes an underlying socket\n * @method\n * @param {Number} code - status code explaining why the connection is being closed\n * @param {String} reason - a description why the connection is closing\n * @return {Undefined}\n * @throws {Error}\n */\n close(code?: number, reason?: string)\n {\n this.socket.close(code, reason)\n }\n\n addEventListener(\n type: K,\n listener: (ev: WebSocketEventMap[K]) => any,\n options?: boolean | AddEventListenerOptions\n ): void\n {\n this.socket.addEventListener(type, listener, options)\n }\n}\n\n/**\n * factory method for common WebSocket instance\n * @method\n * @param {String} address - url to a websocket server\n * @param {(Object)} options - websocket options\n * @return {Undefined}\n */\nexport function WebSocket(\n address: string,\n options: IWSClientAdditionalOptions\n)\n{\n return new WebSocketBrowserImpl(address, options)\n}\n","/**\n * \"Client\" wraps \"ws\" or a browser-implemented \"WebSocket\" library\n * according to the environment providing JSON RPC 2.0 support on top.\n * @module Client\n */\n\n\"use strict\"\n\nimport NodeWebSocket from \"ws\"\nimport { EventEmitter } from \"eventemitter3\"\nimport {\n ICommonWebSocket,\n IWSClientAdditionalOptions,\n NodeWebSocketType,\n ICommonWebSocketFactory,\n} from \"./client/client.types.js\"\n\nimport { DataPack, DefaultDataPack } from \"./utils.js\"\n\ninterface IQueueElement {\n promise: [\n Parameters[0]>[0],\n Parameters[0]>[1]\n ];\n timeout?: ReturnType;\n}\n\nexport interface IQueue {\n [x: number]: IQueueElement;\n}\n\nexport interface IWSRequestParams {\n [x: string]: any;\n [x: number]: any;\n}\n\nexport class CommonClient extends EventEmitter\n{\n private address: string\n private rpc_id: number\n private queue: IQueue\n private options: IWSClientAdditionalOptions & NodeWebSocket.ClientOptions\n private autoconnect: boolean\n private ready: boolean\n private reconnect: boolean\n private reconnect_timer_id: NodeJS.Timeout\n private reconnect_interval: number\n private max_reconnects: number\n private rest_options: IWSClientAdditionalOptions &\n NodeWebSocket.ClientOptions\n private current_reconnects: number\n private generate_request_id: (\n method: string,\n params: object | Array\n ) => number\n private socket: ICommonWebSocket\n private webSocketFactory: ICommonWebSocketFactory\n private dataPack: DataPack\n\n /**\n * Instantiate a Client class.\n * @constructor\n * @param {webSocketFactory} webSocketFactory - factory method for WebSocket\n * @param {String} address - url to a websocket server\n * @param {Object} options - ws options object with reconnect parameters\n * @param {Function} generate_request_id - custom generation request Id\n * @param {DataPack} dataPack - data pack contains encoder and decoder\n * @return {CommonClient}\n */\n constructor(\n webSocketFactory: ICommonWebSocketFactory,\n address = \"ws://localhost:8080\",\n {\n autoconnect = true,\n reconnect = true,\n reconnect_interval = 1000,\n max_reconnects = 5,\n ...rest_options\n } = {},\n generate_request_id?: (\n method: string,\n params: object | Array\n ) => number,\n dataPack?: DataPack\n )\n {\n super()\n\n this.webSocketFactory = webSocketFactory\n\n this.queue = {}\n this.rpc_id = 0\n\n this.address = address\n this.autoconnect = autoconnect\n this.ready = false\n this.reconnect = reconnect\n this.reconnect_timer_id = undefined\n this.reconnect_interval = reconnect_interval\n this.max_reconnects = max_reconnects\n this.rest_options = rest_options\n this.current_reconnects = 0\n this.generate_request_id = generate_request_id || (() => ++this.rpc_id)\n\n if (!dataPack) this.dataPack = new DefaultDataPack()\n else this.dataPack = dataPack\n\n if (this.autoconnect)\n this._connect(this.address, {\n autoconnect: this.autoconnect,\n reconnect: this.reconnect,\n reconnect_interval: this.reconnect_interval,\n max_reconnects: this.max_reconnects,\n ...this.rest_options,\n })\n }\n\n /**\n * Connects to a defined server if not connected already.\n * @method\n * @return {Undefined}\n */\n connect()\n {\n if (this.socket) return\n\n this._connect(this.address, {\n autoconnect: this.autoconnect,\n reconnect: this.reconnect,\n reconnect_interval: this.reconnect_interval,\n max_reconnects: this.max_reconnects,\n ...this.rest_options,\n })\n }\n\n /**\n * Calls a registered RPC method on server.\n * @method\n * @param {String} method - RPC method name\n * @param {Object|Array} params - optional method parameters\n * @param {Number} timeout - RPC reply timeout value\n * @param {Object} ws_opts - options passed to ws\n * @return {Promise}\n */\n call(\n method: string,\n params?: IWSRequestParams,\n timeout?: number,\n ws_opts?: Parameters[1]\n )\n {\n if (!ws_opts && \"object\" === typeof timeout)\n {\n ws_opts = timeout\n timeout = null\n }\n\n return new Promise((resolve, reject) =>\n {\n if (!this.ready) return reject(new Error(\"socket not ready\"))\n\n const rpc_id = this.generate_request_id(method, params)\n\n const message = {\n jsonrpc: \"2.0\",\n method: method,\n params: params || undefined,\n id: rpc_id,\n }\n\n this.socket.send(this.dataPack.encode(message), ws_opts, (error) =>\n {\n if (error) return reject(error)\n\n this.queue[rpc_id] = { promise: [resolve, reject] }\n\n if (timeout)\n {\n this.queue[rpc_id].timeout = setTimeout(() =>\n {\n delete this.queue[rpc_id]\n reject(new Error(\"reply timeout\"))\n }, timeout)\n }\n })\n })\n }\n\n /**\n * Logins with the other side of the connection.\n * @method\n * @param {Object} params - Login credentials object\n * @return {Promise}\n */\n async login(params: IWSRequestParams)\n {\n const resp = await this.call(\"rpc.login\", params)\n\n if (!resp) throw new Error(\"authentication failed\")\n\n return resp\n }\n\n /**\n * Fetches a list of client's methods registered on server.\n * @method\n * @return {Array}\n */\n async listMethods()\n {\n return await this.call(\"__listMethods\")\n }\n\n /**\n * Sends a JSON-RPC 2.0 notification to server.\n * @method\n * @param {String} method - RPC method name\n * @param {Object} params - optional method parameters\n * @return {Promise}\n */\n notify(method: string, params?: IWSRequestParams)\n {\n return new Promise((resolve, reject) =>\n {\n if (!this.ready) return reject(new Error(\"socket not ready\"))\n\n const message = {\n jsonrpc: \"2.0\",\n method: method,\n params,\n }\n\n this.socket.send(this.dataPack.encode(message), (error) =>\n {\n if (error) return reject(error)\n\n resolve()\n })\n })\n }\n\n /**\n * Subscribes for a defined event.\n * @method\n * @param {String|Array} event - event name\n * @return {Undefined}\n * @throws {Error}\n */\n async subscribe(event: string | Array)\n {\n if (typeof event === \"string\") event = [event]\n\n const result = await this.call(\"rpc.on\", event)\n\n if (typeof event === \"string\" && result[event] !== \"ok\")\n throw new Error(\n \"Failed subscribing to an event '\" + event + \"' with: \" + result[event]\n )\n\n return result\n }\n\n /**\n * Unsubscribes from a defined event.\n * @method\n * @param {String|Array} event - event name\n * @return {Undefined}\n * @throws {Error}\n */\n async unsubscribe(event: string | Array)\n {\n if (typeof event === \"string\") event = [event]\n\n const result = await this.call(\"rpc.off\", event)\n\n if (typeof event === \"string\" && result[event] !== \"ok\")\n throw new Error(\"Failed unsubscribing from an event with: \" + result)\n\n return result\n }\n\n /**\n * Closes a WebSocket connection gracefully.\n * @method\n * @param {Number} code - socket close code\n * @param {String} data - optional data to be sent before closing\n * @return {Undefined}\n */\n close(code?: number, data?: string)\n {\n this.socket.close(code || 1000, data)\n }\n\n /**\n * Enable / disable automatic reconnection.\n * @method\n * @param {Boolean} reconnect - enable / disable reconnection\n * @return {Undefined}\n */\n setAutoReconnect(reconnect: boolean)\n {\n this.reconnect = reconnect\n }\n\n /**\n * Set the interval between reconnection attempts.\n * @method\n * @param {Number} interval - reconnection interval in milliseconds\n * @return {Undefined}\n */\n setReconnectInterval(interval: number)\n {\n this.reconnect_interval = interval\n }\n\n /**\n * Set the maximum number of reconnection attempts.\n * @method\n * @param {Number} max_reconnects - maximum reconnection attempts\n * @return {Undefined}\n */\n setMaxReconnects(max_reconnects: number)\n {\n this.max_reconnects = max_reconnects\n }\n\n /**\n * Connection/Message handler.\n * @method\n * @private\n * @param {String} address - WebSocket API address\n * @param {Object} options - ws options object\n * @return {Undefined}\n */\n private _connect(\n address: string,\n options: IWSClientAdditionalOptions & NodeWebSocket.ClientOptions\n )\n {\n clearTimeout(this.reconnect_timer_id)\n this.socket = this.webSocketFactory(address, options)\n\n this.socket.addEventListener(\"open\", () =>\n {\n this.ready = true\n this.emit(\"open\")\n this.current_reconnects = 0\n })\n\n this.socket.addEventListener(\"message\", ({ data: message }) =>\n {\n if (message instanceof ArrayBuffer)\n message = Buffer.from(message).toString()\n\n try\n {\n message = this.dataPack.decode(message)\n }\n catch (error)\n {\n return\n }\n\n // check if any listeners are attached and forward event\n if (message.notification && this.listeners(message.notification).length)\n {\n if (!Object.keys(message.params).length)\n return this.emit(message.notification)\n\n const args = [message.notification]\n\n if (message.params.constructor === Object) args.push(message.params)\n // using for-loop instead of unshift/spread because performance is better\n else\n for (let i = 0; i < message.params.length; i++)\n args.push(message.params[i])\n\n // run as microtask so that pending queue messages are resolved first\n // eslint-disable-next-line prefer-spread\n return Promise.resolve().then(() =>\n {\n // eslint-disable-next-line prefer-spread\n this.emit.apply(this, args)\n })\n }\n\n if (!this.queue[message.id])\n {\n // general JSON RPC 2.0 events\n if (message.method)\n {\n // run as microtask so that pending queue messages are resolved first\n return Promise.resolve().then(() =>\n {\n this.emit(message.method, message?.params)\n })\n }\n\n return\n }\n\n // reject early since server's response is invalid\n if (\"error\" in message === \"result\" in message)\n this.queue[message.id].promise[1](\n new Error(\n \"Server response malformed. Response must include either \\\"result\\\"\" +\n \" or \\\"error\\\", but not both.\"\n )\n )\n\n if (this.queue[message.id].timeout)\n clearTimeout(this.queue[message.id].timeout)\n\n if (message.error) this.queue[message.id].promise[1](message.error)\n else this.queue[message.id].promise[0](message.result)\n\n delete this.queue[message.id]\n })\n\n this.socket.addEventListener(\"error\", (error) => this.emit(\"error\", error))\n\n this.socket.addEventListener(\"close\", ({ code, reason }) =>\n {\n if (this.ready)\n // Delay close event until internal state is updated\n setTimeout(() => this.emit(\"close\", code, reason), 0)\n\n this.ready = false\n this.socket = undefined\n\n if (code === 1000) return\n\n this.current_reconnects++\n\n if (\n this.reconnect &&\n (this.max_reconnects > this.current_reconnects ||\n this.max_reconnects === 0)\n )\n this.reconnect_timer_id = setTimeout(\n () => this._connect(address, options),\n this.reconnect_interval\n )\n })\n }\n}\n","\"use strict\"\n\nexport interface DataPack<\n T,\n R extends string | ArrayBufferLike | Blob | ArrayBufferView\n> {\n encode(value: T): R;\n decode(value: R): T;\n}\n\nexport class DefaultDataPack implements DataPack\n{\n encode(value: Object): string\n {\n return JSON.stringify(value)\n }\n\n decode(value: string): Object\n {\n return JSON.parse(value)\n }\n}\n","\"use strict\"\n\nimport { WebSocket } from \"./lib/client/websocket.browser.js\"\nimport { CommonClient } from \"./lib/client.js\"\nimport { IWSClientAdditionalOptions } from \"./lib/client/client.types.js\"\n\nexport class Client extends CommonClient\n{\n constructor(\n address = \"ws://localhost:8080\",\n {\n autoconnect = true,\n reconnect = true,\n reconnect_interval = 1000,\n max_reconnects = 5,\n }: IWSClientAdditionalOptions = {},\n generate_request_id?: (\n method: string,\n params: object | Array\n ) => number\n )\n {\n super(\n WebSocket,\n address,\n {\n autoconnect,\n reconnect,\n reconnect_interval,\n max_reconnects,\n },\n generate_request_id\n )\n }\n}\n\nexport * from \"./lib/client.js\"\nexport * from \"./lib/client/websocket.browser.js\"\nexport * from \"./lib/client/client.types.js\"\nexport * from \"./lib/utils.js\"\n"]} \ No newline at end of file diff --git a/dist/index.cjs b/dist/index.cjs index c2b952a..7f499dd 100644 --- a/dist/index.cjs +++ b/dist/index.cjs @@ -1,22 +1,898 @@ -"use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; +'use strict'; + +var WebSocketImpl = require('ws'); +var eventemitter3 = require('eventemitter3'); +var url = require('url'); +var uuid = require('uuid'); + +function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; } + +var WebSocketImpl__default = /*#__PURE__*/_interopDefault(WebSocketImpl); +var url__default = /*#__PURE__*/_interopDefault(url); + +// src/lib/client/websocket.ts +function WebSocket(address, options) { + return new WebSocketImpl__default.default(address, options); +} + +// src/lib/utils.ts +var DefaultDataPack = class { + encode(value) { + return JSON.stringify(value); + } + decode(value) { + return JSON.parse(value); + } +}; + +// src/lib/client.ts +var CommonClient = class extends eventemitter3.EventEmitter { + address; + rpc_id; + queue; + options; + autoconnect; + ready; + reconnect; + reconnect_timer_id; + reconnect_interval; + max_reconnects; + rest_options; + current_reconnects; + generate_request_id; + socket; + webSocketFactory; + dataPack; + /** + * Instantiate a Client class. + * @constructor + * @param {webSocketFactory} webSocketFactory - factory method for WebSocket + * @param {String} address - url to a websocket server + * @param {Object} options - ws options object with reconnect parameters + * @param {Function} generate_request_id - custom generation request Id + * @param {DataPack} dataPack - data pack contains encoder and decoder + * @return {CommonClient} + */ + constructor(webSocketFactory, address = "ws://localhost:8080", { + autoconnect = true, + reconnect = true, + reconnect_interval = 1e3, + max_reconnects = 5, + ...rest_options + } = {}, generate_request_id, dataPack) { + super(); + this.webSocketFactory = webSocketFactory; + this.queue = {}; + this.rpc_id = 0; + this.address = address; + this.autoconnect = autoconnect; + this.ready = false; + this.reconnect = reconnect; + this.reconnect_timer_id = void 0; + this.reconnect_interval = reconnect_interval; + this.max_reconnects = max_reconnects; + this.rest_options = rest_options; + this.current_reconnects = 0; + this.generate_request_id = generate_request_id || (() => ++this.rpc_id); + if (!dataPack) this.dataPack = new DefaultDataPack(); + else this.dataPack = dataPack; + if (this.autoconnect) + this._connect(this.address, { + autoconnect: this.autoconnect, + reconnect: this.reconnect, + reconnect_interval: this.reconnect_interval, + max_reconnects: this.max_reconnects, + ...this.rest_options + }); + } + /** + * Connects to a defined server if not connected already. + * @method + * @return {Undefined} + */ + connect() { + if (this.socket) return; + this._connect(this.address, { + autoconnect: this.autoconnect, + reconnect: this.reconnect, + reconnect_interval: this.reconnect_interval, + max_reconnects: this.max_reconnects, + ...this.rest_options + }); + } + /** + * Calls a registered RPC method on server. + * @method + * @param {String} method - RPC method name + * @param {Object|Array} params - optional method parameters + * @param {Number} timeout - RPC reply timeout value + * @param {Object} ws_opts - options passed to ws + * @return {Promise} + */ + call(method, params, timeout, ws_opts) { + if (!ws_opts && "object" === typeof timeout) { + ws_opts = timeout; + timeout = null; + } + return new Promise((resolve, reject) => { + if (!this.ready) return reject(new Error("socket not ready")); + const rpc_id = this.generate_request_id(method, params); + const message = { + jsonrpc: "2.0", + method, + params: params || void 0, + id: rpc_id + }; + this.socket.send(this.dataPack.encode(message), ws_opts, (error) => { + if (error) return reject(error); + this.queue[rpc_id] = { promise: [resolve, reject] }; + if (timeout) { + this.queue[rpc_id].timeout = setTimeout(() => { + delete this.queue[rpc_id]; + reject(new Error("reply timeout")); + }, timeout); + } + }); + }); + } + /** + * Logins with the other side of the connection. + * @method + * @param {Object} params - Login credentials object + * @return {Promise} + */ + async login(params) { + const resp = await this.call("rpc.login", params); + if (!resp) throw new Error("authentication failed"); + return resp; + } + /** + * Fetches a list of client's methods registered on server. + * @method + * @return {Array} + */ + async listMethods() { + return await this.call("__listMethods"); + } + /** + * Sends a JSON-RPC 2.0 notification to server. + * @method + * @param {String} method - RPC method name + * @param {Object} params - optional method parameters + * @return {Promise} + */ + notify(method, params) { + return new Promise((resolve, reject) => { + if (!this.ready) return reject(new Error("socket not ready")); + const message = { + jsonrpc: "2.0", + method, + params + }; + this.socket.send(this.dataPack.encode(message), (error) => { + if (error) return reject(error); + resolve(); + }); + }); + } + /** + * Subscribes for a defined event. + * @method + * @param {String|Array} event - event name + * @return {Undefined} + * @throws {Error} + */ + async subscribe(event) { + if (typeof event === "string") event = [event]; + const result = await this.call("rpc.on", event); + if (typeof event === "string" && result[event] !== "ok") + throw new Error( + "Failed subscribing to an event '" + event + "' with: " + result[event] + ); + return result; + } + /** + * Unsubscribes from a defined event. + * @method + * @param {String|Array} event - event name + * @return {Undefined} + * @throws {Error} + */ + async unsubscribe(event) { + if (typeof event === "string") event = [event]; + const result = await this.call("rpc.off", event); + if (typeof event === "string" && result[event] !== "ok") + throw new Error("Failed unsubscribing from an event with: " + result); + return result; + } + /** + * Closes a WebSocket connection gracefully. + * @method + * @param {Number} code - socket close code + * @param {String} data - optional data to be sent before closing + * @return {Undefined} + */ + close(code, data) { + this.socket.close(code || 1e3, data); + } + /** + * Enable / disable automatic reconnection. + * @method + * @param {Boolean} reconnect - enable / disable reconnection + * @return {Undefined} + */ + setAutoReconnect(reconnect) { + this.reconnect = reconnect; + } + /** + * Set the interval between reconnection attempts. + * @method + * @param {Number} interval - reconnection interval in milliseconds + * @return {Undefined} + */ + setReconnectInterval(interval) { + this.reconnect_interval = interval; + } + /** + * Set the maximum number of reconnection attempts. + * @method + * @param {Number} max_reconnects - maximum reconnection attempts + * @return {Undefined} + */ + setMaxReconnects(max_reconnects) { + this.max_reconnects = max_reconnects; + } + /** + * Connection/Message handler. + * @method + * @private + * @param {String} address - WebSocket API address + * @param {Object} options - ws options object + * @return {Undefined} + */ + _connect(address, options) { + clearTimeout(this.reconnect_timer_id); + this.socket = this.webSocketFactory(address, options); + this.socket.addEventListener("open", () => { + this.ready = true; + this.emit("open"); + this.current_reconnects = 0; + }); + this.socket.addEventListener("message", ({ data: message }) => { + if (message instanceof ArrayBuffer) + message = Buffer.from(message).toString(); + try { + message = this.dataPack.decode(message); + } catch (error) { + return; + } + if (message.notification && this.listeners(message.notification).length) { + if (!Object.keys(message.params).length) + return this.emit(message.notification); + const args = [message.notification]; + if (message.params.constructor === Object) args.push(message.params); + else + for (let i = 0; i < message.params.length; i++) + args.push(message.params[i]); + return Promise.resolve().then(() => { + this.emit.apply(this, args); + }); + } + if (!this.queue[message.id]) { + if (message.method) { + return Promise.resolve().then(() => { + this.emit(message.method, message?.params); + }); + } + return; + } + if ("error" in message === "result" in message) + this.queue[message.id].promise[1]( + new Error( + 'Server response malformed. Response must include either "result" or "error", but not both.' + ) + ); + if (this.queue[message.id].timeout) + clearTimeout(this.queue[message.id].timeout); + if (message.error) this.queue[message.id].promise[1](message.error); + else this.queue[message.id].promise[0](message.result); + delete this.queue[message.id]; + }); + this.socket.addEventListener("error", (error) => this.emit("error", error)); + this.socket.addEventListener("close", ({ code, reason }) => { + if (this.ready) + setTimeout(() => this.emit("close", code, reason), 0); + this.ready = false; + this.socket = void 0; + if (code === 1e3) return; + this.current_reconnects++; + if (this.reconnect && (this.max_reconnects > this.current_reconnects || this.max_reconnects === 0)) + this.reconnect_timer_id = setTimeout( + () => this._connect(address, options), + this.reconnect_interval + ); + }); + } }; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.Server = exports.Client = void 0; -const websocket_cjs_1 = __importDefault(require("./lib/client/websocket.cjs")); -const client_cjs_1 = __importDefault(require("./lib/client.cjs")); -class Client extends client_cjs_1.default { - constructor(address = "ws://localhost:8080", { autoconnect = true, reconnect = true, reconnect_interval = 1000, max_reconnects = 5, ...rest_options } = {}, generate_request_id) { - super(websocket_cjs_1.default, address, { - autoconnect, - reconnect, - reconnect_interval, - max_reconnects, - ...rest_options - }, generate_request_id); +var Server = class extends eventemitter3.EventEmitter { + namespaces; + dataPack; + wss; + /** + * Instantiate a Server class. + * @constructor + * @param {Object} options - ws constructor's parameters with rpc + * @param {DataPack} dataPack - data pack contains encoder and decoder + * @return {Server} - returns a new Server instance + */ + constructor(options, dataPack) { + super(); + this.namespaces = {}; + if (!dataPack) this.dataPack = new DefaultDataPack(); + else this.dataPack = dataPack; + this.wss = new WebSocketImpl.WebSocketServer(options); + this.wss.on("listening", () => this.emit("listening")); + this.wss.on("connection", (socket, request) => { + const u = url__default.default.parse(request.url, true); + const ns = u.pathname; + if (u.query.socket_id) socket._id = u.query.socket_id; + else socket._id = uuid.v1(); + socket["_authenticated"] = false; + socket.on("error", (error) => this.emit("socket-error", socket, error)); + socket.on("close", () => { + this.namespaces[ns].clients.delete(socket._id); + for (const event of Object.keys(this.namespaces[ns].events)) { + const index = this.namespaces[ns].events[event].sockets.indexOf( + socket._id + ); + if (index >= 0) + this.namespaces[ns].events[event].sockets.splice(index, 1); + } + this.emit("disconnection", socket); + }); + if (!this.namespaces[ns]) this._generateNamespace(ns); + this.namespaces[ns].clients.set(socket._id, socket); + this.emit("connection", socket, request); + return this._handleRPC(socket, ns); + }); + this.wss.on("error", (error) => this.emit("error", error)); + } + /** + * Registers an RPC method. + * @method + * @param {String} name - method name + * @param {Function} fn - a callee function + * @param {String} ns - namespace identifier + * @throws {TypeError} + * @return {Object} - returns an IMethod object + */ + register(name, fn, ns = "/") { + if (!this.namespaces[ns]) this._generateNamespace(ns); + this.namespaces[ns].rpc_methods[name] = { + fn, + protected: false + }; + return { + protected: () => this._makeProtectedMethod(name, ns), + public: () => this._makePublicMethod(name, ns) + }; + } + /** + * Sets an auth method. + * @method + * @param {Function} fn - an arbitrary auth method + * @param {String} ns - namespace identifier + * @throws {TypeError} + * @return {Undefined} + */ + setAuth(fn, ns = "/") { + this.register("rpc.login", fn, ns); + } + /** + * Marks an RPC method as protected. + * @method + * @param {String} name - method name + * @param {String} ns - namespace identifier + * @return {Undefined} + */ + _makeProtectedMethod(name, ns = "/") { + this.namespaces[ns].rpc_methods[name].protected = true; + } + /** + * Marks an RPC method as public. + * @method + * @param {String} name - method name + * @param {String} ns - namespace identifier + * @return {Undefined} + */ + _makePublicMethod(name, ns = "/") { + this.namespaces[ns].rpc_methods[name].protected = false; + } + /** + * Marks an event as protected. + * @method + * @param {String} name - event name + * @param {String} ns - namespace identifier + * @return {Undefined} + */ + _makeProtectedEvent(name, ns = "/") { + this.namespaces[ns].events[name].protected = true; + } + /** + * Marks an event as public. + * @method + * @param {String} name - event name + * @param {String} ns - namespace identifier + * @return {Undefined} + */ + _makePublicEvent(name, ns = "/") { + this.namespaces[ns].events[name].protected = false; + } + /** + * Removes a namespace and closes all connections + * @method + * @param {String} ns - namespace identifier + * @throws {TypeError} + * @return {Undefined} + */ + closeNamespace(ns) { + const namespace = this.namespaces[ns]; + if (namespace) { + delete namespace.rpc_methods; + delete namespace.events; + for (const socket of namespace.clients.values()) socket.close(); + delete this.namespaces[ns]; + } + } + /** + * Creates a new event that can be emitted to clients. + * @method + * @param {String} name - event name + * @param {String} ns - namespace identifier + * @throws {TypeError} + * @return {Object} - returns an IEvent object + */ + event(name, ns = "/") { + if (!this.namespaces[ns]) this._generateNamespace(ns); + else { + const index = this.namespaces[ns].events[name]; + if (index !== void 0) + throw new Error(`Already registered event ${ns}${name}`); + } + this.namespaces[ns].events[name] = { + sockets: [], + protected: false + }; + this.on(name, (...params) => { + if (params.length === 1 && params[0] instanceof Object) + params = params[0]; + for (const socket_id of this.namespaces[ns].events[name].sockets) { + const socket = this.namespaces[ns].clients.get(socket_id); + if (!socket) continue; + socket.send( + this.dataPack.encode({ + notification: name, + params + }) + ); + } + }); + return { + protected: () => this._makeProtectedEvent(name, ns), + public: () => this._makePublicEvent(name, ns) + }; + } + /** + * Returns a requested namespace object + * @method + * @param {String} name - namespace identifier + * @throws {TypeError} + * @return {Object} - namespace object + */ + of(name) { + if (!this.namespaces[name]) this._generateNamespace(name); + const self = this; + return { + // self.register convenience method + register(fn_name, fn) { + if (arguments.length !== 2) + throw new Error("must provide exactly two arguments"); + if (typeof fn_name !== "string") + throw new Error("name must be a string"); + if (typeof fn !== "function") + throw new Error("handler must be a function"); + return self.register(fn_name, fn, name); + }, + // self.event convenience method + event(ev_name) { + if (arguments.length !== 1) + throw new Error("must provide exactly one argument"); + if (typeof ev_name !== "string") + throw new Error("name must be a string"); + return self.event(ev_name, name); + }, + // self.eventList convenience method + get eventList() { + return Object.keys(self.namespaces[name].events); + }, + /** + * Emits a specified event to this namespace. + * @inner + * @method + * @param {String} event - event name + * @param {Array} params - event parameters + * @return {Undefined} + */ + emit(event, ...params) { + const socket_ids = [...self.namespaces[name].clients.keys()]; + for (let i = 0, id; id = socket_ids[i]; ++i) { + self.namespaces[name].clients.get(id).send( + self.dataPack.encode({ + notification: event, + params: params || [] + }) + ); + } + }, + /** + * Returns a name of this namespace. + * @inner + * @method + * @kind constant + * @return {String} + */ + get name() { + return name; + }, + /** + * Returns a hash of websocket objects connected to this namespace. + * @inner + * @method + * @return {Object} + */ + connected() { + const socket_ids = [...self.namespaces[name].clients.keys()]; + return socket_ids.reduce( + (acc, curr) => ({ + ...acc, + [curr]: self.namespaces[name].clients.get(curr) + }), + {} + ); + }, + /** + * Returns a list of client unique identifiers connected to this namespace. + * @inner + * @method + * @return {Array} + */ + clients() { + return self.namespaces[name]; + } + }; + } + /** + * Lists all created events in a given namespace. Defaults to "/". + * @method + * @param {String} ns - namespaces identifier + * @readonly + * @return {Array} - returns a list of created events + */ + eventList(ns = "/") { + if (!this.namespaces[ns]) return []; + return Object.keys(this.namespaces[ns].events); + } + /** + * Creates a JSON-RPC 2.0 compliant error + * @method + * @param {Number} code - indicates the error type that occurred + * @param {String} message - provides a short description of the error + * @param {String|Object} data - details containing additional information about the error + * @return {Object} + */ + createError(code, message, data) { + return { + code, + message, + data: data || null + }; + } + /** + * Closes the server and terminates all clients. + * @method + * @return {Promise} + */ + close() { + return new Promise((resolve, reject) => { + try { + this.wss.close(); + this.emit("close"); + resolve(); + } catch (error) { + reject(error); + } + }); + } + /** + * Handles all WebSocket JSON RPC 2.0 requests. + * @private + * @param {Object} socket - ws socket instance + * @param {String} ns - namespaces identifier + * @return {Undefined} + */ + _handleRPC(socket, ns = "/") { + socket.on("message", async (data) => { + const msg_options = {}; + if (data instanceof ArrayBuffer) { + msg_options.binary = true; + data = Buffer.from(data).toString(); + } + if (socket.readyState !== 1) return; + let parsedData; + try { + parsedData = this.dataPack.decode(data); + } catch (error) { + return socket.send( + this.dataPack.encode({ + jsonrpc: "2.0", + error: createError(-32700, error.toString()), + id: null + }), + msg_options + ); + } + if (Array.isArray(parsedData)) { + if (!parsedData.length) + return socket.send( + this.dataPack.encode({ + jsonrpc: "2.0", + error: createError(-32600, "Invalid array"), + id: null + }), + msg_options + ); + const responses = []; + for (const message of parsedData) { + const response2 = await this._runMethod(message, socket._id, ns); + if (!response2) continue; + responses.push(response2); + } + if (!responses.length) return; + return socket.send(this.dataPack.encode(responses), msg_options); + } + const response = await this._runMethod(parsedData, socket._id, ns); + if (!response) return; + return socket.send(this.dataPack.encode(response), msg_options); + }); + } + /** + * Runs a defined RPC method. + * @private + * @param {Object} message - a message received + * @param {Object} socket_id - user's socket id + * @param {String} ns - namespaces identifier + * @return {Object|undefined} + */ + async _runMethod(message, socket_id, ns = "/") { + if (typeof message !== "object" || message === null) + return { + jsonrpc: "2.0", + error: createError(-32600), + id: null + }; + if (message.jsonrpc !== "2.0") + return { + jsonrpc: "2.0", + error: createError(-32600, "Invalid JSON RPC version"), + id: message.id || null + }; + if (!message.method) + return { + jsonrpc: "2.0", + error: createError(-32602, "Method not specified"), + id: message.id || null + }; + if (typeof message.method !== "string") + return { + jsonrpc: "2.0", + error: createError(-32600, "Invalid method name"), + id: message.id || null + }; + if (message.params && typeof message.params === "string") + return { + jsonrpc: "2.0", + error: createError(-32600), + id: message.id || null + }; + if (message.method === "rpc.on") { + if (!message.params) + return { + jsonrpc: "2.0", + error: createError(-32e3), + id: message.id || null + }; + const results = {}; + const event_names = Object.keys(this.namespaces[ns].events); + for (const name of message.params) { + const index = event_names.indexOf(name); + const namespace = this.namespaces[ns]; + if (index === -1) { + results[name] = "provided event invalid"; + continue; + } + if (namespace.events[event_names[index]].protected === true && namespace.clients.get(socket_id)["_authenticated"] === false) { + return { + jsonrpc: "2.0", + error: createError(-32606), + id: message.id || null + }; + } + const socket_index = namespace.events[event_names[index]].sockets.indexOf(socket_id); + if (socket_index >= 0) { + results[name] = "socket has already been subscribed to event"; + continue; + } + namespace.events[event_names[index]].sockets.push(socket_id); + results[name] = "ok"; + } + return { + jsonrpc: "2.0", + result: results, + id: message.id || null + }; + } else if (message.method === "rpc.off") { + if (!message.params) + return { + jsonrpc: "2.0", + error: createError(-32e3), + id: message.id || null + }; + const results = {}; + for (const name of message.params) { + if (!this.namespaces[ns].events[name]) { + results[name] = "provided event invalid"; + continue; + } + const index = this.namespaces[ns].events[name].sockets.indexOf(socket_id); + if (index === -1) { + results[name] = "not subscribed"; + continue; + } + this.namespaces[ns].events[name].sockets.splice(index, 1); + results[name] = "ok"; + } + return { + jsonrpc: "2.0", + result: results, + id: message.id || null + }; + } else if (message.method === "rpc.login") { + if (!message.params) + return { + jsonrpc: "2.0", + error: createError(-32604), + id: message.id || null + }; + } + if (!this.namespaces[ns].rpc_methods[message.method]) { + return { + jsonrpc: "2.0", + error: createError(-32601), + id: message.id || null + }; } + let response = null; + if (this.namespaces[ns].rpc_methods[message.method].protected === true && this.namespaces[ns].clients.get(socket_id)["_authenticated"] === false) { + return { + jsonrpc: "2.0", + error: createError(-32605), + id: message.id || null + }; + } + try { + response = await this.namespaces[ns].rpc_methods[message.method].fn( + message.params, + socket_id + ); + } catch (error) { + if (!message.id) return; + if (error instanceof Error) + return { + jsonrpc: "2.0", + error: { + code: -32e3, + message: error.name, + data: error.message + }, + id: message.id + }; + return { + jsonrpc: "2.0", + error, + id: message.id + }; + } + if (!message.id) return; + if (message.method === "rpc.login" && response === true) { + const s = this.namespaces[ns].clients.get(socket_id); + s["_authenticated"] = true; + this.namespaces[ns].clients.set(socket_id, s); + } + return { + jsonrpc: "2.0", + result: response, + id: message.id + }; + } + /** + * Generate a new namespace store. + * Also preregister some special namespace methods. + * @private + * @param {String} name - namespaces identifier + * @return {undefined} + */ + _generateNamespace(name) { + this.namespaces[name] = { + rpc_methods: { + __listMethods: { + fn: () => Object.keys(this.namespaces[name].rpc_methods), + protected: false + } + }, + clients: /* @__PURE__ */ new Map(), + events: {} + }; + } +}; +var RPC_ERRORS = /* @__PURE__ */ new Map([ + [-32e3, "Event not provided"], + [-32600, "Invalid Request"], + [-32601, "Method not found"], + [-32602, "Invalid params"], + [-32603, "Internal error"], + [-32604, "Params not found"], + [-32605, "Method forbidden"], + [-32606, "Event forbidden"], + [-32700, "Parse error"] +]); +function createError(code, details) { + const error = { + code, + message: RPC_ERRORS.get(code) || "Internal Server Error" + }; + if (details) error["data"] = details; + return error; } + +// src/index.ts +var Client = class extends CommonClient { + constructor(address = "ws://localhost:8080", { + autoconnect = true, + reconnect = true, + reconnect_interval = 1e3, + max_reconnects = 5, + ...rest_options + } = {}, generate_request_id) { + super( + WebSocket, + address, + { + autoconnect, + reconnect, + reconnect_interval, + max_reconnects, + ...rest_options + }, + generate_request_id + ); + } +}; + exports.Client = Client; -var server_cjs_1 = require("./lib/server.cjs"); -Object.defineProperty(exports, "Server", { enumerable: true, get: function () { return __importDefault(server_cjs_1).default; } }); +exports.CommonClient = CommonClient; +exports.DefaultDataPack = DefaultDataPack; +exports.Server = Server; +exports.WebSocket = WebSocket; +exports.createError = createError; +//# sourceMappingURL=out.js.map +//# sourceMappingURL=index.cjs.map \ No newline at end of file diff --git a/dist/index.cjs.map b/dist/index.cjs.map new file mode 100644 index 0000000..6e99d14 --- /dev/null +++ b/dist/index.cjs.map @@ -0,0 +1 @@ +{"version":3,"sources":["../src/lib/client/websocket.ts","../src/lib/client.ts","../src/lib/utils.ts","../src/lib/server.ts","../src/index.ts"],"names":["EventEmitter","response"],"mappings":"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","sourcesContent":["/* A wrapper for the \"qaap/uws-bindings\" library. */\n\n\"use strict\"\n\nimport WebSocketImpl from \"ws\"\n\nimport { IWSClientAdditionalOptions } from \"./client.types.js\"\n\n/**\n * factory method for common WebSocket instance\n * @method\n * @param {String} address - url to a websocket server\n * @param {(Object)} options - websocket options\n * @return {Undefined}\n */\nexport function WebSocket(\n address: string,\n options: IWSClientAdditionalOptions & WebSocketImpl.ClientOptions\n)\n{\n return new WebSocketImpl(address, options)\n}\n","/**\n * \"Client\" wraps \"ws\" or a browser-implemented \"WebSocket\" library\n * according to the environment providing JSON RPC 2.0 support on top.\n * @module Client\n */\n\n\"use strict\"\n\nimport NodeWebSocket from \"ws\"\nimport { EventEmitter } from \"eventemitter3\"\nimport {\n ICommonWebSocket,\n IWSClientAdditionalOptions,\n NodeWebSocketType,\n ICommonWebSocketFactory,\n} from \"./client/client.types.js\"\n\nimport { DataPack, DefaultDataPack } from \"./utils.js\"\n\ninterface IQueueElement {\n promise: [\n Parameters[0]>[0],\n Parameters[0]>[1]\n ];\n timeout?: ReturnType;\n}\n\nexport interface IQueue {\n [x: number]: IQueueElement;\n}\n\nexport interface IWSRequestParams {\n [x: string]: any;\n [x: number]: any;\n}\n\nexport class CommonClient extends EventEmitter\n{\n private address: string\n private rpc_id: number\n private queue: IQueue\n private options: IWSClientAdditionalOptions & NodeWebSocket.ClientOptions\n private autoconnect: boolean\n private ready: boolean\n private reconnect: boolean\n private reconnect_timer_id: NodeJS.Timeout\n private reconnect_interval: number\n private max_reconnects: number\n private rest_options: IWSClientAdditionalOptions &\n NodeWebSocket.ClientOptions\n private current_reconnects: number\n private generate_request_id: (\n method: string,\n params: object | Array\n ) => number\n private socket: ICommonWebSocket\n private webSocketFactory: ICommonWebSocketFactory\n private dataPack: DataPack\n\n /**\n * Instantiate a Client class.\n * @constructor\n * @param {webSocketFactory} webSocketFactory - factory method for WebSocket\n * @param {String} address - url to a websocket server\n * @param {Object} options - ws options object with reconnect parameters\n * @param {Function} generate_request_id - custom generation request Id\n * @param {DataPack} dataPack - data pack contains encoder and decoder\n * @return {CommonClient}\n */\n constructor(\n webSocketFactory: ICommonWebSocketFactory,\n address = \"ws://localhost:8080\",\n {\n autoconnect = true,\n reconnect = true,\n reconnect_interval = 1000,\n max_reconnects = 5,\n ...rest_options\n } = {},\n generate_request_id?: (\n method: string,\n params: object | Array\n ) => number,\n dataPack?: DataPack\n )\n {\n super()\n\n this.webSocketFactory = webSocketFactory\n\n this.queue = {}\n this.rpc_id = 0\n\n this.address = address\n this.autoconnect = autoconnect\n this.ready = false\n this.reconnect = reconnect\n this.reconnect_timer_id = undefined\n this.reconnect_interval = reconnect_interval\n this.max_reconnects = max_reconnects\n this.rest_options = rest_options\n this.current_reconnects = 0\n this.generate_request_id = generate_request_id || (() => ++this.rpc_id)\n\n if (!dataPack) this.dataPack = new DefaultDataPack()\n else this.dataPack = dataPack\n\n if (this.autoconnect)\n this._connect(this.address, {\n autoconnect: this.autoconnect,\n reconnect: this.reconnect,\n reconnect_interval: this.reconnect_interval,\n max_reconnects: this.max_reconnects,\n ...this.rest_options,\n })\n }\n\n /**\n * Connects to a defined server if not connected already.\n * @method\n * @return {Undefined}\n */\n connect()\n {\n if (this.socket) return\n\n this._connect(this.address, {\n autoconnect: this.autoconnect,\n reconnect: this.reconnect,\n reconnect_interval: this.reconnect_interval,\n max_reconnects: this.max_reconnects,\n ...this.rest_options,\n })\n }\n\n /**\n * Calls a registered RPC method on server.\n * @method\n * @param {String} method - RPC method name\n * @param {Object|Array} params - optional method parameters\n * @param {Number} timeout - RPC reply timeout value\n * @param {Object} ws_opts - options passed to ws\n * @return {Promise}\n */\n call(\n method: string,\n params?: IWSRequestParams,\n timeout?: number,\n ws_opts?: Parameters[1]\n )\n {\n if (!ws_opts && \"object\" === typeof timeout)\n {\n ws_opts = timeout\n timeout = null\n }\n\n return new Promise((resolve, reject) =>\n {\n if (!this.ready) return reject(new Error(\"socket not ready\"))\n\n const rpc_id = this.generate_request_id(method, params)\n\n const message = {\n jsonrpc: \"2.0\",\n method: method,\n params: params || undefined,\n id: rpc_id,\n }\n\n this.socket.send(this.dataPack.encode(message), ws_opts, (error) =>\n {\n if (error) return reject(error)\n\n this.queue[rpc_id] = { promise: [resolve, reject] }\n\n if (timeout)\n {\n this.queue[rpc_id].timeout = setTimeout(() =>\n {\n delete this.queue[rpc_id]\n reject(new Error(\"reply timeout\"))\n }, timeout)\n }\n })\n })\n }\n\n /**\n * Logins with the other side of the connection.\n * @method\n * @param {Object} params - Login credentials object\n * @return {Promise}\n */\n async login(params: IWSRequestParams)\n {\n const resp = await this.call(\"rpc.login\", params)\n\n if (!resp) throw new Error(\"authentication failed\")\n\n return resp\n }\n\n /**\n * Fetches a list of client's methods registered on server.\n * @method\n * @return {Array}\n */\n async listMethods()\n {\n return await this.call(\"__listMethods\")\n }\n\n /**\n * Sends a JSON-RPC 2.0 notification to server.\n * @method\n * @param {String} method - RPC method name\n * @param {Object} params - optional method parameters\n * @return {Promise}\n */\n notify(method: string, params?: IWSRequestParams)\n {\n return new Promise((resolve, reject) =>\n {\n if (!this.ready) return reject(new Error(\"socket not ready\"))\n\n const message = {\n jsonrpc: \"2.0\",\n method: method,\n params,\n }\n\n this.socket.send(this.dataPack.encode(message), (error) =>\n {\n if (error) return reject(error)\n\n resolve()\n })\n })\n }\n\n /**\n * Subscribes for a defined event.\n * @method\n * @param {String|Array} event - event name\n * @return {Undefined}\n * @throws {Error}\n */\n async subscribe(event: string | Array)\n {\n if (typeof event === \"string\") event = [event]\n\n const result = await this.call(\"rpc.on\", event)\n\n if (typeof event === \"string\" && result[event] !== \"ok\")\n throw new Error(\n \"Failed subscribing to an event '\" + event + \"' with: \" + result[event]\n )\n\n return result\n }\n\n /**\n * Unsubscribes from a defined event.\n * @method\n * @param {String|Array} event - event name\n * @return {Undefined}\n * @throws {Error}\n */\n async unsubscribe(event: string | Array)\n {\n if (typeof event === \"string\") event = [event]\n\n const result = await this.call(\"rpc.off\", event)\n\n if (typeof event === \"string\" && result[event] !== \"ok\")\n throw new Error(\"Failed unsubscribing from an event with: \" + result)\n\n return result\n }\n\n /**\n * Closes a WebSocket connection gracefully.\n * @method\n * @param {Number} code - socket close code\n * @param {String} data - optional data to be sent before closing\n * @return {Undefined}\n */\n close(code?: number, data?: string)\n {\n this.socket.close(code || 1000, data)\n }\n\n /**\n * Enable / disable automatic reconnection.\n * @method\n * @param {Boolean} reconnect - enable / disable reconnection\n * @return {Undefined}\n */\n setAutoReconnect(reconnect: boolean)\n {\n this.reconnect = reconnect\n }\n\n /**\n * Set the interval between reconnection attempts.\n * @method\n * @param {Number} interval - reconnection interval in milliseconds\n * @return {Undefined}\n */\n setReconnectInterval(interval: number)\n {\n this.reconnect_interval = interval\n }\n\n /**\n * Set the maximum number of reconnection attempts.\n * @method\n * @param {Number} max_reconnects - maximum reconnection attempts\n * @return {Undefined}\n */\n setMaxReconnects(max_reconnects: number)\n {\n this.max_reconnects = max_reconnects\n }\n\n /**\n * Connection/Message handler.\n * @method\n * @private\n * @param {String} address - WebSocket API address\n * @param {Object} options - ws options object\n * @return {Undefined}\n */\n private _connect(\n address: string,\n options: IWSClientAdditionalOptions & NodeWebSocket.ClientOptions\n )\n {\n clearTimeout(this.reconnect_timer_id)\n this.socket = this.webSocketFactory(address, options)\n\n this.socket.addEventListener(\"open\", () =>\n {\n this.ready = true\n this.emit(\"open\")\n this.current_reconnects = 0\n })\n\n this.socket.addEventListener(\"message\", ({ data: message }) =>\n {\n if (message instanceof ArrayBuffer)\n message = Buffer.from(message).toString()\n\n try\n {\n message = this.dataPack.decode(message)\n }\n catch (error)\n {\n return\n }\n\n // check if any listeners are attached and forward event\n if (message.notification && this.listeners(message.notification).length)\n {\n if (!Object.keys(message.params).length)\n return this.emit(message.notification)\n\n const args = [message.notification]\n\n if (message.params.constructor === Object) args.push(message.params)\n // using for-loop instead of unshift/spread because performance is better\n else\n for (let i = 0; i < message.params.length; i++)\n args.push(message.params[i])\n\n // run as microtask so that pending queue messages are resolved first\n // eslint-disable-next-line prefer-spread\n return Promise.resolve().then(() =>\n {\n // eslint-disable-next-line prefer-spread\n this.emit.apply(this, args)\n })\n }\n\n if (!this.queue[message.id])\n {\n // general JSON RPC 2.0 events\n if (message.method)\n {\n // run as microtask so that pending queue messages are resolved first\n return Promise.resolve().then(() =>\n {\n this.emit(message.method, message?.params)\n })\n }\n\n return\n }\n\n // reject early since server's response is invalid\n if (\"error\" in message === \"result\" in message)\n this.queue[message.id].promise[1](\n new Error(\n \"Server response malformed. Response must include either \\\"result\\\"\" +\n \" or \\\"error\\\", but not both.\"\n )\n )\n\n if (this.queue[message.id].timeout)\n clearTimeout(this.queue[message.id].timeout)\n\n if (message.error) this.queue[message.id].promise[1](message.error)\n else this.queue[message.id].promise[0](message.result)\n\n delete this.queue[message.id]\n })\n\n this.socket.addEventListener(\"error\", (error) => this.emit(\"error\", error))\n\n this.socket.addEventListener(\"close\", ({ code, reason }) =>\n {\n if (this.ready)\n // Delay close event until internal state is updated\n setTimeout(() => this.emit(\"close\", code, reason), 0)\n\n this.ready = false\n this.socket = undefined\n\n if (code === 1000) return\n\n this.current_reconnects++\n\n if (\n this.reconnect &&\n (this.max_reconnects > this.current_reconnects ||\n this.max_reconnects === 0)\n )\n this.reconnect_timer_id = setTimeout(\n () => this._connect(address, options),\n this.reconnect_interval\n )\n })\n }\n}\n","\"use strict\"\n\nexport interface DataPack<\n T,\n R extends string | ArrayBufferLike | Blob | ArrayBufferView\n> {\n encode(value: T): R;\n decode(value: R): T;\n}\n\nexport class DefaultDataPack implements DataPack\n{\n encode(value: Object): string\n {\n return JSON.stringify(value)\n }\n\n decode(value: string): Object\n {\n return JSON.parse(value)\n }\n}\n","/**\n * \"Server\" wraps the \"ws\" library providing JSON RPC 2.0 support on top.\n * @module Server\n */\n\n\"use strict\"\n\nimport { EventEmitter } from \"eventemitter3\"\nimport url from \"node:url\"\nimport { v1 as uuidv1 } from \"uuid\"\nimport NodeWebSocket, { WebSocketServer } from \"ws\"\n\nimport { DataPack, DefaultDataPack } from \"./utils.js\"\n\ninterface INamespaceEvent {\n [x: string]: {\n sockets: Array;\n protected: boolean;\n };\n}\n\ninterface IMethod {\n public: () => void;\n protected: () => void;\n}\n\ninterface IEvent {\n public: () => void;\n protected: () => void;\n}\n\ninterface IRPCError {\n code: number;\n message: string;\n data?: string;\n}\n\ninterface IRPCMethodParams {\n [x: string]: any;\n}\n\ninterface IRPCMethod {\n [x: string]: {\n fn: (params: IRPCMethodParams, socket_id: string) => any;\n protected: boolean;\n };\n}\n\ninterface INamespace {\n [x: string]: {\n rpc_methods: IRPCMethod;\n clients: Map;\n events: INamespaceEvent;\n };\n}\n\ninterface IClientWebSocket extends NodeWebSocket {\n _id: string;\n _authenticated: boolean;\n}\n\ninterface IRPCResult {\n [x: string]: string;\n}\n\nexport class Server extends EventEmitter\n{\n private namespaces: INamespace\n private dataPack: DataPack\n wss: InstanceType\n\n /**\n * Instantiate a Server class.\n * @constructor\n * @param {Object} options - ws constructor's parameters with rpc\n * @param {DataPack} dataPack - data pack contains encoder and decoder\n * @return {Server} - returns a new Server instance\n */\n constructor(\n options: NodeWebSocket.ServerOptions,\n dataPack?: DataPack\n )\n {\n super()\n\n /**\n * Stores all connected sockets with a universally unique identifier\n * in the appropriate namespace.\n * Stores all rpc methods to specific namespaces. \"/\" by default.\n * Stores all events as keys and subscribed users in array as value\n * @private\n * @name namespaces\n * @param {Object} namespaces.rpc_methods\n * @param {Map} namespaces.clients\n * @param {Object} namespaces.events\n */\n this.namespaces = {}\n\n if (!dataPack) this.dataPack = new DefaultDataPack()\n else this.dataPack = dataPack\n\n this.wss = new WebSocketServer(options)\n\n this.wss.on(\"listening\", () => this.emit(\"listening\"))\n\n this.wss.on(\"connection\", (socket: IClientWebSocket, request) =>\n {\n const u = url.parse(request.url, true)\n const ns = u.pathname\n\n if (u.query.socket_id) socket._id = u.query.socket_id as string\n else socket._id = uuidv1()\n\n // unauthenticated by default\n socket[\"_authenticated\"] = false\n\n // propagate socket errors\n socket.on(\"error\", (error) => this.emit(\"socket-error\", socket, error))\n\n // cleanup after the socket gets disconnected\n socket.on(\"close\", () =>\n {\n this.namespaces[ns].clients.delete(socket._id)\n\n for (const event of Object.keys(this.namespaces[ns].events))\n {\n const index = this.namespaces[ns].events[event].sockets.indexOf(\n socket._id\n )\n\n if (index >= 0)\n this.namespaces[ns].events[event].sockets.splice(index, 1)\n }\n\n this.emit(\"disconnection\", socket)\n })\n\n if (!this.namespaces[ns]) this._generateNamespace(ns)\n\n // store socket and method\n this.namespaces[ns].clients.set(socket._id, socket)\n\n this.emit(\"connection\", socket, request)\n\n return this._handleRPC(socket, ns)\n })\n\n this.wss.on(\"error\", (error) => this.emit(\"error\", error))\n }\n\n /**\n * Registers an RPC method.\n * @method\n * @param {String} name - method name\n * @param {Function} fn - a callee function\n * @param {String} ns - namespace identifier\n * @throws {TypeError}\n * @return {Object} - returns an IMethod object\n */\n register(\n name: string,\n fn: (params: IRPCMethodParams, socket_id: string) => void,\n ns = \"/\"\n )\n {\n if (!this.namespaces[ns]) this._generateNamespace(ns)\n\n this.namespaces[ns].rpc_methods[name] = {\n fn: fn,\n protected: false,\n }\n\n return {\n protected: () => this._makeProtectedMethod(name, ns),\n public: () => this._makePublicMethod(name, ns),\n } as IMethod\n }\n\n /**\n * Sets an auth method.\n * @method\n * @param {Function} fn - an arbitrary auth method\n * @param {String} ns - namespace identifier\n * @throws {TypeError}\n * @return {Undefined}\n */\n setAuth(\n fn: (params: IRPCMethodParams, socket_id: string) => Promise,\n ns = \"/\"\n )\n {\n this.register(\"rpc.login\", fn, ns)\n }\n\n /**\n * Marks an RPC method as protected.\n * @method\n * @param {String} name - method name\n * @param {String} ns - namespace identifier\n * @return {Undefined}\n */\n private _makeProtectedMethod(name: string, ns = \"/\")\n {\n this.namespaces[ns].rpc_methods[name].protected = true\n }\n\n /**\n * Marks an RPC method as public.\n * @method\n * @param {String} name - method name\n * @param {String} ns - namespace identifier\n * @return {Undefined}\n */\n private _makePublicMethod(name: string, ns = \"/\")\n {\n this.namespaces[ns].rpc_methods[name].protected = false\n }\n\n /**\n * Marks an event as protected.\n * @method\n * @param {String} name - event name\n * @param {String} ns - namespace identifier\n * @return {Undefined}\n */\n private _makeProtectedEvent(name: string, ns = \"/\")\n {\n this.namespaces[ns].events[name].protected = true\n }\n\n /**\n * Marks an event as public.\n * @method\n * @param {String} name - event name\n * @param {String} ns - namespace identifier\n * @return {Undefined}\n */\n private _makePublicEvent(name: string, ns = \"/\")\n {\n this.namespaces[ns].events[name].protected = false\n }\n\n /**\n * Removes a namespace and closes all connections\n * @method\n * @param {String} ns - namespace identifier\n * @throws {TypeError}\n * @return {Undefined}\n */\n closeNamespace(ns: string)\n {\n const namespace = this.namespaces[ns]\n\n if (namespace)\n {\n delete namespace.rpc_methods\n delete namespace.events\n\n for (const socket of namespace.clients.values()) socket.close()\n\n delete this.namespaces[ns]\n }\n }\n\n /**\n * Creates a new event that can be emitted to clients.\n * @method\n * @param {String} name - event name\n * @param {String} ns - namespace identifier\n * @throws {TypeError}\n * @return {Object} - returns an IEvent object\n */\n event(name: string, ns = \"/\"): IEvent\n {\n if (!this.namespaces[ns]) this._generateNamespace(ns)\n else\n {\n const index = this.namespaces[ns].events[name]\n\n if (index !== undefined)\n throw new Error(`Already registered event ${ns}${name}`)\n }\n\n this.namespaces[ns].events[name] = {\n sockets: [],\n protected: false,\n }\n\n // forward emitted event to subscribers\n this.on(name, (...params) =>\n {\n // flatten an object if no spreading is wanted\n if (params.length === 1 && params[0] instanceof Object)\n params = params[0]\n\n for (const socket_id of this.namespaces[ns].events[name].sockets)\n {\n const socket = this.namespaces[ns].clients.get(socket_id)\n\n if (!socket) continue\n\n socket.send(\n this.dataPack.encode({\n notification: name,\n params,\n })\n )\n }\n })\n\n return {\n protected: () => this._makeProtectedEvent(name, ns),\n public: () => this._makePublicEvent(name, ns),\n }\n }\n\n /**\n * Returns a requested namespace object\n * @method\n * @param {String} name - namespace identifier\n * @throws {TypeError}\n * @return {Object} - namespace object\n */\n of(name: string)\n {\n if (!this.namespaces[name]) this._generateNamespace(name)\n\n const self = this\n\n return {\n // self.register convenience method\n register(\n fn_name: string,\n fn: (params: IRPCMethodParams) => void\n ): IMethod\n {\n if (arguments.length !== 2)\n throw new Error(\"must provide exactly two arguments\")\n\n if (typeof fn_name !== \"string\")\n throw new Error(\"name must be a string\")\n\n if (typeof fn !== \"function\")\n throw new Error(\"handler must be a function\")\n\n return self.register(fn_name, fn, name)\n },\n\n // self.event convenience method\n event(ev_name: string): IEvent\n {\n if (arguments.length !== 1)\n throw new Error(\"must provide exactly one argument\")\n\n if (typeof ev_name !== \"string\")\n throw new Error(\"name must be a string\")\n\n return self.event(ev_name, name)\n },\n\n // self.eventList convenience method\n get eventList()\n {\n return Object.keys(self.namespaces[name].events)\n },\n\n /**\n * Emits a specified event to this namespace.\n * @inner\n * @method\n * @param {String} event - event name\n * @param {Array} params - event parameters\n * @return {Undefined}\n */\n emit(event: string, ...params: Array)\n {\n const socket_ids = [...self.namespaces[name].clients.keys()]\n\n for (let i = 0, id; (id = socket_ids[i]); ++i)\n {\n self.namespaces[name].clients.get(id).send(\n self.dataPack.encode({\n notification: event,\n params: params || [],\n })\n )\n }\n },\n\n /**\n * Returns a name of this namespace.\n * @inner\n * @method\n * @kind constant\n * @return {String}\n */\n get name()\n {\n return name\n },\n\n /**\n * Returns a hash of websocket objects connected to this namespace.\n * @inner\n * @method\n * @return {Object}\n */\n connected()\n {\n const socket_ids = [...self.namespaces[name].clients.keys()]\n\n return socket_ids.reduce(\n (acc, curr) => ({\n ...acc,\n [curr]: self.namespaces[name].clients.get(curr),\n }),\n {}\n )\n },\n\n /**\n * Returns a list of client unique identifiers connected to this namespace.\n * @inner\n * @method\n * @return {Array}\n */\n clients()\n {\n return self.namespaces[name]\n },\n }\n }\n\n /**\n * Lists all created events in a given namespace. Defaults to \"/\".\n * @method\n * @param {String} ns - namespaces identifier\n * @readonly\n * @return {Array} - returns a list of created events\n */\n eventList(ns = \"/\")\n {\n if (!this.namespaces[ns]) return []\n\n return Object.keys(this.namespaces[ns].events)\n }\n\n /**\n * Creates a JSON-RPC 2.0 compliant error\n * @method\n * @param {Number} code - indicates the error type that occurred\n * @param {String} message - provides a short description of the error\n * @param {String|Object} data - details containing additional information about the error\n * @return {Object}\n */\n createError(code: number, message: string, data: string | object)\n {\n return {\n code: code,\n message: message,\n data: data || null,\n }\n }\n\n /**\n * Closes the server and terminates all clients.\n * @method\n * @return {Promise}\n */\n close()\n {\n return new Promise((resolve, reject) =>\n {\n try\n {\n this.wss.close()\n this.emit(\"close\")\n resolve()\n }\n catch (error)\n {\n reject(error)\n }\n })\n }\n\n /**\n * Handles all WebSocket JSON RPC 2.0 requests.\n * @private\n * @param {Object} socket - ws socket instance\n * @param {String} ns - namespaces identifier\n * @return {Undefined}\n */\n private _handleRPC(socket: IClientWebSocket, ns = \"/\")\n {\n socket.on(\"message\", async (data: any) =>\n {\n const msg_options: Parameters[1] = {}\n\n if (data instanceof ArrayBuffer)\n {\n msg_options.binary = true\n\n data = Buffer.from(data).toString()\n }\n\n if (socket.readyState !== 1) return // TODO: should have debug logs here\n\n let parsedData: any\n\n try\n {\n parsedData = this.dataPack.decode(data as string)\n }\n catch (error)\n {\n return socket.send(\n this.dataPack.encode({\n jsonrpc: \"2.0\",\n error: createError(-32700, error.toString()),\n id: null,\n }),\n msg_options\n )\n }\n\n if (Array.isArray(parsedData))\n {\n if (!parsedData.length)\n return socket.send(\n this.dataPack.encode({\n jsonrpc: \"2.0\",\n error: createError(-32600, \"Invalid array\"),\n id: null,\n }),\n msg_options\n )\n\n const responses = []\n\n for (const message of parsedData)\n {\n const response = await this._runMethod(message, socket._id, ns)\n\n if (!response) continue\n\n responses.push(response)\n }\n\n if (!responses.length) return\n\n return socket.send(this.dataPack.encode(responses), msg_options)\n }\n\n const response = await this._runMethod(parsedData, socket._id, ns)\n\n if (!response) return\n\n return socket.send(this.dataPack.encode(response), msg_options)\n })\n }\n\n /**\n * Runs a defined RPC method.\n * @private\n * @param {Object} message - a message received\n * @param {Object} socket_id - user's socket id\n * @param {String} ns - namespaces identifier\n * @return {Object|undefined}\n */\n private async _runMethod(message: any, socket_id: string, ns = \"/\")\n {\n if (typeof message !== \"object\" || message === null)\n return {\n jsonrpc: \"2.0\",\n error: createError(-32600),\n id: null,\n }\n\n if (message.jsonrpc !== \"2.0\")\n return {\n jsonrpc: \"2.0\",\n error: createError(-32600, \"Invalid JSON RPC version\"),\n id: message.id || null,\n }\n\n if (!message.method)\n return {\n jsonrpc: \"2.0\",\n error: createError(-32602, \"Method not specified\"),\n id: message.id || null,\n }\n\n if (typeof message.method !== \"string\")\n return {\n jsonrpc: \"2.0\",\n error: createError(-32600, \"Invalid method name\"),\n id: message.id || null,\n }\n\n if (message.params && typeof message.params === \"string\")\n return {\n jsonrpc: \"2.0\",\n error: createError(-32600),\n id: message.id || null,\n }\n\n if (message.method === \"rpc.on\")\n {\n if (!message.params)\n return {\n jsonrpc: \"2.0\",\n error: createError(-32000),\n id: message.id || null,\n }\n\n const results: IRPCMethodParams = {}\n\n const event_names = Object.keys(this.namespaces[ns].events)\n\n for (const name of message.params)\n {\n const index = event_names.indexOf(name)\n const namespace = this.namespaces[ns]\n\n if (index === -1)\n {\n results[name] = \"provided event invalid\"\n continue\n }\n\n // reject request if event is protected and if client is not authenticated\n if (\n namespace.events[event_names[index]].protected === true &&\n namespace.clients.get(socket_id)[\"_authenticated\"] === false\n )\n {\n return {\n jsonrpc: \"2.0\",\n error: createError(-32606),\n id: message.id || null,\n }\n }\n\n const socket_index =\n namespace.events[event_names[index]].sockets.indexOf(socket_id)\n if (socket_index >= 0)\n {\n results[name] = \"socket has already been subscribed to event\"\n continue\n }\n namespace.events[event_names[index]].sockets.push(socket_id)\n\n results[name] = \"ok\"\n }\n\n return {\n jsonrpc: \"2.0\",\n result: results,\n id: message.id || null,\n }\n }\n else if (message.method === \"rpc.off\")\n {\n if (!message.params)\n return {\n jsonrpc: \"2.0\",\n error: createError(-32000),\n id: message.id || null,\n }\n\n const results: IRPCResult = {}\n\n for (const name of message.params)\n {\n if (!this.namespaces[ns].events[name])\n {\n results[name] = \"provided event invalid\"\n continue\n }\n\n const index =\n this.namespaces[ns].events[name].sockets.indexOf(socket_id)\n\n if (index === -1)\n {\n results[name] = \"not subscribed\"\n continue\n }\n\n this.namespaces[ns].events[name].sockets.splice(index, 1)\n results[name] = \"ok\"\n }\n\n return {\n jsonrpc: \"2.0\",\n result: results,\n id: message.id || null,\n }\n }\n else if (message.method === \"rpc.login\")\n {\n if (!message.params)\n return {\n jsonrpc: \"2.0\",\n error: createError(-32604),\n id: message.id || null,\n }\n }\n\n if (!this.namespaces[ns].rpc_methods[message.method])\n {\n return {\n jsonrpc: \"2.0\",\n error: createError(-32601),\n id: message.id || null,\n }\n }\n\n let response = null\n\n // reject request if method is protected and if client is not authenticated\n if (\n this.namespaces[ns].rpc_methods[message.method].protected === true &&\n this.namespaces[ns].clients.get(socket_id)[\"_authenticated\"] === false\n )\n {\n return {\n jsonrpc: \"2.0\",\n error: createError(-32605),\n id: message.id || null,\n }\n }\n\n try\n {\n response = await this.namespaces[ns].rpc_methods[message.method].fn(\n message.params,\n socket_id\n )\n }\n catch (error)\n {\n if (!message.id) return\n\n if (error instanceof Error)\n return {\n jsonrpc: \"2.0\",\n error: {\n code: -32000,\n message: error.name,\n data: error.message,\n },\n id: message.id,\n }\n\n return {\n jsonrpc: \"2.0\",\n error: error,\n id: message.id,\n }\n }\n\n // client sent a notification, so we won't need a reply\n if (!message.id) return\n\n // if login middleware returned true, set connection as authenticated\n if (message.method === \"rpc.login\" && response === true)\n {\n const s = this.namespaces[ns].clients.get(socket_id)\n s[\"_authenticated\"] = true\n this.namespaces[ns].clients.set(socket_id, s)\n }\n\n return {\n jsonrpc: \"2.0\",\n result: response,\n id: message.id,\n }\n }\n\n /**\n * Generate a new namespace store.\n * Also preregister some special namespace methods.\n * @private\n * @param {String} name - namespaces identifier\n * @return {undefined}\n */\n private _generateNamespace(name: string)\n {\n this.namespaces[name] = {\n rpc_methods: {\n __listMethods: {\n fn: () => Object.keys(this.namespaces[name].rpc_methods),\n protected: false,\n },\n },\n clients: new Map(),\n events: {},\n }\n }\n}\n\nconst RPC_ERRORS = new Map([\n [-32000, \"Event not provided\"],\n [-32600, \"Invalid Request\"],\n [-32601, \"Method not found\"],\n [-32602, \"Invalid params\"],\n [-32603, \"Internal error\"],\n [-32604, \"Params not found\"],\n [-32605, \"Method forbidden\"],\n [-32606, \"Event forbidden\"],\n [-32700, \"Parse error\"],\n])\n\n/**\n * Creates a JSON-RPC 2.0-compliant error.\n * @param {Number} code - error code\n * @param {String} details - error details\n * @return {Object}\n */\nexport function createError(code: number, details?: string)\n{\n const error: IRPCError = {\n code: code,\n message: RPC_ERRORS.get(code) || \"Internal Server Error\",\n }\n\n if (details) error[\"data\"] = details\n\n return error\n}\n","\"use strict\"\n\nimport { WebSocket } from \"./lib/client/websocket.js\"\nimport { CommonClient } from \"./lib/client.js\"\nimport {\n NodeWebSocketTypeOptions,\n IWSClientAdditionalOptions,\n ICommonWebSocketFactory,\n} from \"./lib/client/client.types.js\"\n\nexport class Client extends CommonClient\n{\n constructor(\n address = \"ws://localhost:8080\",\n {\n autoconnect = true,\n reconnect = true,\n reconnect_interval = 1000,\n max_reconnects = 5,\n ...rest_options\n }: IWSClientAdditionalOptions & NodeWebSocketTypeOptions = {},\n generate_request_id?: (\n method: string,\n params: object | Array\n ) => number\n )\n {\n super(\n WebSocket as ICommonWebSocketFactory,\n address,\n {\n autoconnect,\n reconnect,\n reconnect_interval,\n max_reconnects,\n ...rest_options,\n },\n generate_request_id\n )\n }\n}\n\nexport * from \"./lib/client.js\"\nexport * from \"./lib/client/websocket.js\"\nexport * from \"./lib/client/client.types.js\"\nexport * from \"./lib/server.js\"\nexport * from \"./lib/utils.js\""]} \ No newline at end of file diff --git a/dist/index.d.cts b/dist/index.d.cts deleted file mode 100644 index ac84bc8..0000000 --- a/dist/index.d.cts +++ /dev/null @@ -1,6 +0,0 @@ -import CommonClient from "./lib/client.cjs"; -import { NodeWebSocketTypeOptions, IWSClientAdditionalOptions } from "./lib/client/client.types.cjs"; -export declare class Client extends CommonClient { - constructor(address?: string, { autoconnect, reconnect, reconnect_interval, max_reconnects, ...rest_options }?: IWSClientAdditionalOptions & NodeWebSocketTypeOptions, generate_request_id?: (method: string, params: object | Array) => number); -} -export { default as Server } from "./lib/server.cjs"; diff --git a/dist/index.d.mts b/dist/index.d.mts new file mode 100644 index 0000000..19c0b1b --- /dev/null +++ b/dist/index.d.mts @@ -0,0 +1,415 @@ +import { EventEmitter } from 'eventemitter3'; +import NodeWebSocket, { WebSocketServer } from 'ws'; + +type BrowserWebSocketType = InstanceType; +type NodeWebSocketType = InstanceType; +type NodeWebSocketTypeOptions = NodeWebSocket.ClientOptions; +interface IWSClientAdditionalOptions { + autoconnect?: boolean; + reconnect?: boolean; + reconnect_interval?: number; + max_reconnects?: number; +} +interface ICommonWebSocketFactory { + (address: string, options: IWSClientAdditionalOptions): ICommonWebSocket; +} +interface ICommonWebSocket { + send: (data: Parameters[0], optionsOrCallback: ((error?: Error) => void) | Parameters[1], callback?: (error?: Error) => void) => void; + close: (code?: number, reason?: string) => void; + addEventListener(type: K, listener: (ev: WebSocketEventMap[K]) => any, options?: boolean | AddEventListenerOptions): void; +} + +interface DataPack { + encode(value: T): R; + decode(value: R): T; +} +declare class DefaultDataPack implements DataPack { + encode(value: Object): string; + decode(value: string): Object; +} + +/** + * "Client" wraps "ws" or a browser-implemented "WebSocket" library + * according to the environment providing JSON RPC 2.0 support on top. + * @module Client + */ + +interface IQueueElement { + promise: [ + Parameters[0]>[0], + Parameters[0]>[1] + ]; + timeout?: ReturnType; +} +interface IQueue { + [x: number]: IQueueElement; +} +interface IWSRequestParams { + [x: string]: any; + [x: number]: any; +} +declare class CommonClient extends EventEmitter { + private address; + private rpc_id; + private queue; + private options; + private autoconnect; + private ready; + private reconnect; + private reconnect_timer_id; + private reconnect_interval; + private max_reconnects; + private rest_options; + private current_reconnects; + private generate_request_id; + private socket; + private webSocketFactory; + private dataPack; + /** + * Instantiate a Client class. + * @constructor + * @param {webSocketFactory} webSocketFactory - factory method for WebSocket + * @param {String} address - url to a websocket server + * @param {Object} options - ws options object with reconnect parameters + * @param {Function} generate_request_id - custom generation request Id + * @param {DataPack} dataPack - data pack contains encoder and decoder + * @return {CommonClient} + */ + constructor(webSocketFactory: ICommonWebSocketFactory, address?: string, { autoconnect, reconnect, reconnect_interval, max_reconnects, ...rest_options }?: { + autoconnect?: boolean; + reconnect?: boolean; + reconnect_interval?: number; + max_reconnects?: number; + }, generate_request_id?: (method: string, params: object | Array) => number, dataPack?: DataPack); + /** + * Connects to a defined server if not connected already. + * @method + * @return {Undefined} + */ + connect(): void; + /** + * Calls a registered RPC method on server. + * @method + * @param {String} method - RPC method name + * @param {Object|Array} params - optional method parameters + * @param {Number} timeout - RPC reply timeout value + * @param {Object} ws_opts - options passed to ws + * @return {Promise} + */ + call(method: string, params?: IWSRequestParams, timeout?: number, ws_opts?: Parameters[1]): Promise; + /** + * Logins with the other side of the connection. + * @method + * @param {Object} params - Login credentials object + * @return {Promise} + */ + login(params: IWSRequestParams): Promise; + /** + * Fetches a list of client's methods registered on server. + * @method + * @return {Array} + */ + listMethods(): Promise; + /** + * Sends a JSON-RPC 2.0 notification to server. + * @method + * @param {String} method - RPC method name + * @param {Object} params - optional method parameters + * @return {Promise} + */ + notify(method: string, params?: IWSRequestParams): Promise; + /** + * Subscribes for a defined event. + * @method + * @param {String|Array} event - event name + * @return {Undefined} + * @throws {Error} + */ + subscribe(event: string | Array): Promise; + /** + * Unsubscribes from a defined event. + * @method + * @param {String|Array} event - event name + * @return {Undefined} + * @throws {Error} + */ + unsubscribe(event: string | Array): Promise; + /** + * Closes a WebSocket connection gracefully. + * @method + * @param {Number} code - socket close code + * @param {String} data - optional data to be sent before closing + * @return {Undefined} + */ + close(code?: number, data?: string): void; + /** + * Enable / disable automatic reconnection. + * @method + * @param {Boolean} reconnect - enable / disable reconnection + * @return {Undefined} + */ + setAutoReconnect(reconnect: boolean): void; + /** + * Set the interval between reconnection attempts. + * @method + * @param {Number} interval - reconnection interval in milliseconds + * @return {Undefined} + */ + setReconnectInterval(interval: number): void; + /** + * Set the maximum number of reconnection attempts. + * @method + * @param {Number} max_reconnects - maximum reconnection attempts + * @return {Undefined} + */ + setMaxReconnects(max_reconnects: number): void; + /** + * Connection/Message handler. + * @method + * @private + * @param {String} address - WebSocket API address + * @param {Object} options - ws options object + * @return {Undefined} + */ + private _connect; +} + +/** + * factory method for common WebSocket instance + * @method + * @param {String} address - url to a websocket server + * @param {(Object)} options - websocket options + * @return {Undefined} + */ +declare function WebSocket$1(address: string, options: IWSClientAdditionalOptions & NodeWebSocket.ClientOptions): NodeWebSocket; + +/** + * "Server" wraps the "ws" library providing JSON RPC 2.0 support on top. + * @module Server + */ + +interface INamespaceEvent { + [x: string]: { + sockets: Array; + protected: boolean; + }; +} +interface IMethod { + public: () => void; + protected: () => void; +} +interface IEvent { + public: () => void; + protected: () => void; +} +interface IRPCError { + code: number; + message: string; + data?: string; +} +interface IRPCMethodParams { + [x: string]: any; +} +interface IRPCMethod { + [x: string]: { + fn: (params: IRPCMethodParams, socket_id: string) => any; + protected: boolean; + }; +} +interface IClientWebSocket extends NodeWebSocket { + _id: string; + _authenticated: boolean; +} +declare class Server extends EventEmitter { + private namespaces; + private dataPack; + wss: InstanceType; + /** + * Instantiate a Server class. + * @constructor + * @param {Object} options - ws constructor's parameters with rpc + * @param {DataPack} dataPack - data pack contains encoder and decoder + * @return {Server} - returns a new Server instance + */ + constructor(options: NodeWebSocket.ServerOptions, dataPack?: DataPack); + /** + * Registers an RPC method. + * @method + * @param {String} name - method name + * @param {Function} fn - a callee function + * @param {String} ns - namespace identifier + * @throws {TypeError} + * @return {Object} - returns an IMethod object + */ + register(name: string, fn: (params: IRPCMethodParams, socket_id: string) => void, ns?: string): IMethod; + /** + * Sets an auth method. + * @method + * @param {Function} fn - an arbitrary auth method + * @param {String} ns - namespace identifier + * @throws {TypeError} + * @return {Undefined} + */ + setAuth(fn: (params: IRPCMethodParams, socket_id: string) => Promise, ns?: string): void; + /** + * Marks an RPC method as protected. + * @method + * @param {String} name - method name + * @param {String} ns - namespace identifier + * @return {Undefined} + */ + private _makeProtectedMethod; + /** + * Marks an RPC method as public. + * @method + * @param {String} name - method name + * @param {String} ns - namespace identifier + * @return {Undefined} + */ + private _makePublicMethod; + /** + * Marks an event as protected. + * @method + * @param {String} name - event name + * @param {String} ns - namespace identifier + * @return {Undefined} + */ + private _makeProtectedEvent; + /** + * Marks an event as public. + * @method + * @param {String} name - event name + * @param {String} ns - namespace identifier + * @return {Undefined} + */ + private _makePublicEvent; + /** + * Removes a namespace and closes all connections + * @method + * @param {String} ns - namespace identifier + * @throws {TypeError} + * @return {Undefined} + */ + closeNamespace(ns: string): void; + /** + * Creates a new event that can be emitted to clients. + * @method + * @param {String} name - event name + * @param {String} ns - namespace identifier + * @throws {TypeError} + * @return {Object} - returns an IEvent object + */ + event(name: string, ns?: string): IEvent; + /** + * Returns a requested namespace object + * @method + * @param {String} name - namespace identifier + * @throws {TypeError} + * @return {Object} - namespace object + */ + of(name: string): { + register(fn_name: string, fn: (params: IRPCMethodParams) => void): IMethod; + event(ev_name: string): IEvent; + readonly eventList: string[]; + /** + * Emits a specified event to this namespace. + * @inner + * @method + * @param {String} event - event name + * @param {Array} params - event parameters + * @return {Undefined} + */ + emit(event: string, ...params: Array): void; + /** + * Returns a name of this namespace. + * @inner + * @method + * @kind constant + * @return {String} + */ + readonly name: string; + /** + * Returns a hash of websocket objects connected to this namespace. + * @inner + * @method + * @return {Object} + */ + connected(): {}; + /** + * Returns a list of client unique identifiers connected to this namespace. + * @inner + * @method + * @return {Array} + */ + clients(): { + rpc_methods: IRPCMethod; + clients: Map; + events: INamespaceEvent; + }; + }; + /** + * Lists all created events in a given namespace. Defaults to "/". + * @method + * @param {String} ns - namespaces identifier + * @readonly + * @return {Array} - returns a list of created events + */ + eventList(ns?: string): string[]; + /** + * Creates a JSON-RPC 2.0 compliant error + * @method + * @param {Number} code - indicates the error type that occurred + * @param {String} message - provides a short description of the error + * @param {String|Object} data - details containing additional information about the error + * @return {Object} + */ + createError(code: number, message: string, data: string | object): { + code: number; + message: string; + data: string | object; + }; + /** + * Closes the server and terminates all clients. + * @method + * @return {Promise} + */ + close(): Promise; + /** + * Handles all WebSocket JSON RPC 2.0 requests. + * @private + * @param {Object} socket - ws socket instance + * @param {String} ns - namespaces identifier + * @return {Undefined} + */ + private _handleRPC; + /** + * Runs a defined RPC method. + * @private + * @param {Object} message - a message received + * @param {Object} socket_id - user's socket id + * @param {String} ns - namespaces identifier + * @return {Object|undefined} + */ + private _runMethod; + /** + * Generate a new namespace store. + * Also preregister some special namespace methods. + * @private + * @param {String} name - namespaces identifier + * @return {undefined} + */ + private _generateNamespace; +} +/** + * Creates a JSON-RPC 2.0-compliant error. + * @param {Number} code - error code + * @param {String} details - error details + * @return {Object} + */ +declare function createError(code: number, details?: string): IRPCError; + +declare class Client extends CommonClient { + constructor(address?: string, { autoconnect, reconnect, reconnect_interval, max_reconnects, ...rest_options }?: IWSClientAdditionalOptions & NodeWebSocketTypeOptions, generate_request_id?: (method: string, params: object | Array) => number); +} + +export { type BrowserWebSocketType, Client, CommonClient, type DataPack, DefaultDataPack, type ICommonWebSocket, type ICommonWebSocketFactory, type IQueue, type IWSClientAdditionalOptions, type IWSRequestParams, type NodeWebSocketType, type NodeWebSocketTypeOptions, Server, WebSocket$1 as WebSocket, createError }; diff --git a/dist/index.d.ts b/dist/index.d.ts new file mode 100644 index 0000000..19c0b1b --- /dev/null +++ b/dist/index.d.ts @@ -0,0 +1,415 @@ +import { EventEmitter } from 'eventemitter3'; +import NodeWebSocket, { WebSocketServer } from 'ws'; + +type BrowserWebSocketType = InstanceType; +type NodeWebSocketType = InstanceType; +type NodeWebSocketTypeOptions = NodeWebSocket.ClientOptions; +interface IWSClientAdditionalOptions { + autoconnect?: boolean; + reconnect?: boolean; + reconnect_interval?: number; + max_reconnects?: number; +} +interface ICommonWebSocketFactory { + (address: string, options: IWSClientAdditionalOptions): ICommonWebSocket; +} +interface ICommonWebSocket { + send: (data: Parameters[0], optionsOrCallback: ((error?: Error) => void) | Parameters[1], callback?: (error?: Error) => void) => void; + close: (code?: number, reason?: string) => void; + addEventListener(type: K, listener: (ev: WebSocketEventMap[K]) => any, options?: boolean | AddEventListenerOptions): void; +} + +interface DataPack { + encode(value: T): R; + decode(value: R): T; +} +declare class DefaultDataPack implements DataPack { + encode(value: Object): string; + decode(value: string): Object; +} + +/** + * "Client" wraps "ws" or a browser-implemented "WebSocket" library + * according to the environment providing JSON RPC 2.0 support on top. + * @module Client + */ + +interface IQueueElement { + promise: [ + Parameters[0]>[0], + Parameters[0]>[1] + ]; + timeout?: ReturnType; +} +interface IQueue { + [x: number]: IQueueElement; +} +interface IWSRequestParams { + [x: string]: any; + [x: number]: any; +} +declare class CommonClient extends EventEmitter { + private address; + private rpc_id; + private queue; + private options; + private autoconnect; + private ready; + private reconnect; + private reconnect_timer_id; + private reconnect_interval; + private max_reconnects; + private rest_options; + private current_reconnects; + private generate_request_id; + private socket; + private webSocketFactory; + private dataPack; + /** + * Instantiate a Client class. + * @constructor + * @param {webSocketFactory} webSocketFactory - factory method for WebSocket + * @param {String} address - url to a websocket server + * @param {Object} options - ws options object with reconnect parameters + * @param {Function} generate_request_id - custom generation request Id + * @param {DataPack} dataPack - data pack contains encoder and decoder + * @return {CommonClient} + */ + constructor(webSocketFactory: ICommonWebSocketFactory, address?: string, { autoconnect, reconnect, reconnect_interval, max_reconnects, ...rest_options }?: { + autoconnect?: boolean; + reconnect?: boolean; + reconnect_interval?: number; + max_reconnects?: number; + }, generate_request_id?: (method: string, params: object | Array) => number, dataPack?: DataPack); + /** + * Connects to a defined server if not connected already. + * @method + * @return {Undefined} + */ + connect(): void; + /** + * Calls a registered RPC method on server. + * @method + * @param {String} method - RPC method name + * @param {Object|Array} params - optional method parameters + * @param {Number} timeout - RPC reply timeout value + * @param {Object} ws_opts - options passed to ws + * @return {Promise} + */ + call(method: string, params?: IWSRequestParams, timeout?: number, ws_opts?: Parameters[1]): Promise; + /** + * Logins with the other side of the connection. + * @method + * @param {Object} params - Login credentials object + * @return {Promise} + */ + login(params: IWSRequestParams): Promise; + /** + * Fetches a list of client's methods registered on server. + * @method + * @return {Array} + */ + listMethods(): Promise; + /** + * Sends a JSON-RPC 2.0 notification to server. + * @method + * @param {String} method - RPC method name + * @param {Object} params - optional method parameters + * @return {Promise} + */ + notify(method: string, params?: IWSRequestParams): Promise; + /** + * Subscribes for a defined event. + * @method + * @param {String|Array} event - event name + * @return {Undefined} + * @throws {Error} + */ + subscribe(event: string | Array): Promise; + /** + * Unsubscribes from a defined event. + * @method + * @param {String|Array} event - event name + * @return {Undefined} + * @throws {Error} + */ + unsubscribe(event: string | Array): Promise; + /** + * Closes a WebSocket connection gracefully. + * @method + * @param {Number} code - socket close code + * @param {String} data - optional data to be sent before closing + * @return {Undefined} + */ + close(code?: number, data?: string): void; + /** + * Enable / disable automatic reconnection. + * @method + * @param {Boolean} reconnect - enable / disable reconnection + * @return {Undefined} + */ + setAutoReconnect(reconnect: boolean): void; + /** + * Set the interval between reconnection attempts. + * @method + * @param {Number} interval - reconnection interval in milliseconds + * @return {Undefined} + */ + setReconnectInterval(interval: number): void; + /** + * Set the maximum number of reconnection attempts. + * @method + * @param {Number} max_reconnects - maximum reconnection attempts + * @return {Undefined} + */ + setMaxReconnects(max_reconnects: number): void; + /** + * Connection/Message handler. + * @method + * @private + * @param {String} address - WebSocket API address + * @param {Object} options - ws options object + * @return {Undefined} + */ + private _connect; +} + +/** + * factory method for common WebSocket instance + * @method + * @param {String} address - url to a websocket server + * @param {(Object)} options - websocket options + * @return {Undefined} + */ +declare function WebSocket$1(address: string, options: IWSClientAdditionalOptions & NodeWebSocket.ClientOptions): NodeWebSocket; + +/** + * "Server" wraps the "ws" library providing JSON RPC 2.0 support on top. + * @module Server + */ + +interface INamespaceEvent { + [x: string]: { + sockets: Array; + protected: boolean; + }; +} +interface IMethod { + public: () => void; + protected: () => void; +} +interface IEvent { + public: () => void; + protected: () => void; +} +interface IRPCError { + code: number; + message: string; + data?: string; +} +interface IRPCMethodParams { + [x: string]: any; +} +interface IRPCMethod { + [x: string]: { + fn: (params: IRPCMethodParams, socket_id: string) => any; + protected: boolean; + }; +} +interface IClientWebSocket extends NodeWebSocket { + _id: string; + _authenticated: boolean; +} +declare class Server extends EventEmitter { + private namespaces; + private dataPack; + wss: InstanceType; + /** + * Instantiate a Server class. + * @constructor + * @param {Object} options - ws constructor's parameters with rpc + * @param {DataPack} dataPack - data pack contains encoder and decoder + * @return {Server} - returns a new Server instance + */ + constructor(options: NodeWebSocket.ServerOptions, dataPack?: DataPack); + /** + * Registers an RPC method. + * @method + * @param {String} name - method name + * @param {Function} fn - a callee function + * @param {String} ns - namespace identifier + * @throws {TypeError} + * @return {Object} - returns an IMethod object + */ + register(name: string, fn: (params: IRPCMethodParams, socket_id: string) => void, ns?: string): IMethod; + /** + * Sets an auth method. + * @method + * @param {Function} fn - an arbitrary auth method + * @param {String} ns - namespace identifier + * @throws {TypeError} + * @return {Undefined} + */ + setAuth(fn: (params: IRPCMethodParams, socket_id: string) => Promise, ns?: string): void; + /** + * Marks an RPC method as protected. + * @method + * @param {String} name - method name + * @param {String} ns - namespace identifier + * @return {Undefined} + */ + private _makeProtectedMethod; + /** + * Marks an RPC method as public. + * @method + * @param {String} name - method name + * @param {String} ns - namespace identifier + * @return {Undefined} + */ + private _makePublicMethod; + /** + * Marks an event as protected. + * @method + * @param {String} name - event name + * @param {String} ns - namespace identifier + * @return {Undefined} + */ + private _makeProtectedEvent; + /** + * Marks an event as public. + * @method + * @param {String} name - event name + * @param {String} ns - namespace identifier + * @return {Undefined} + */ + private _makePublicEvent; + /** + * Removes a namespace and closes all connections + * @method + * @param {String} ns - namespace identifier + * @throws {TypeError} + * @return {Undefined} + */ + closeNamespace(ns: string): void; + /** + * Creates a new event that can be emitted to clients. + * @method + * @param {String} name - event name + * @param {String} ns - namespace identifier + * @throws {TypeError} + * @return {Object} - returns an IEvent object + */ + event(name: string, ns?: string): IEvent; + /** + * Returns a requested namespace object + * @method + * @param {String} name - namespace identifier + * @throws {TypeError} + * @return {Object} - namespace object + */ + of(name: string): { + register(fn_name: string, fn: (params: IRPCMethodParams) => void): IMethod; + event(ev_name: string): IEvent; + readonly eventList: string[]; + /** + * Emits a specified event to this namespace. + * @inner + * @method + * @param {String} event - event name + * @param {Array} params - event parameters + * @return {Undefined} + */ + emit(event: string, ...params: Array): void; + /** + * Returns a name of this namespace. + * @inner + * @method + * @kind constant + * @return {String} + */ + readonly name: string; + /** + * Returns a hash of websocket objects connected to this namespace. + * @inner + * @method + * @return {Object} + */ + connected(): {}; + /** + * Returns a list of client unique identifiers connected to this namespace. + * @inner + * @method + * @return {Array} + */ + clients(): { + rpc_methods: IRPCMethod; + clients: Map; + events: INamespaceEvent; + }; + }; + /** + * Lists all created events in a given namespace. Defaults to "/". + * @method + * @param {String} ns - namespaces identifier + * @readonly + * @return {Array} - returns a list of created events + */ + eventList(ns?: string): string[]; + /** + * Creates a JSON-RPC 2.0 compliant error + * @method + * @param {Number} code - indicates the error type that occurred + * @param {String} message - provides a short description of the error + * @param {String|Object} data - details containing additional information about the error + * @return {Object} + */ + createError(code: number, message: string, data: string | object): { + code: number; + message: string; + data: string | object; + }; + /** + * Closes the server and terminates all clients. + * @method + * @return {Promise} + */ + close(): Promise; + /** + * Handles all WebSocket JSON RPC 2.0 requests. + * @private + * @param {Object} socket - ws socket instance + * @param {String} ns - namespaces identifier + * @return {Undefined} + */ + private _handleRPC; + /** + * Runs a defined RPC method. + * @private + * @param {Object} message - a message received + * @param {Object} socket_id - user's socket id + * @param {String} ns - namespaces identifier + * @return {Object|undefined} + */ + private _runMethod; + /** + * Generate a new namespace store. + * Also preregister some special namespace methods. + * @private + * @param {String} name - namespaces identifier + * @return {undefined} + */ + private _generateNamespace; +} +/** + * Creates a JSON-RPC 2.0-compliant error. + * @param {Number} code - error code + * @param {String} details - error details + * @return {Object} + */ +declare function createError(code: number, details?: string): IRPCError; + +declare class Client extends CommonClient { + constructor(address?: string, { autoconnect, reconnect, reconnect_interval, max_reconnects, ...rest_options }?: IWSClientAdditionalOptions & NodeWebSocketTypeOptions, generate_request_id?: (method: string, params: object | Array) => number); +} + +export { type BrowserWebSocketType, Client, CommonClient, type DataPack, DefaultDataPack, type ICommonWebSocket, type ICommonWebSocketFactory, type IQueue, type IWSClientAdditionalOptions, type IWSRequestParams, type NodeWebSocketType, type NodeWebSocketTypeOptions, Server, WebSocket$1 as WebSocket, createError }; diff --git a/dist/index.mjs b/dist/index.mjs new file mode 100644 index 0000000..d127eed --- /dev/null +++ b/dist/index.mjs @@ -0,0 +1,886 @@ +import WebSocketImpl, { WebSocketServer } from 'ws'; +import { EventEmitter } from 'eventemitter3'; +import url from 'node:url'; +import { v1 } from 'uuid'; + +// src/lib/client/websocket.ts +function WebSocket(address, options) { + return new WebSocketImpl(address, options); +} + +// src/lib/utils.ts +var DefaultDataPack = class { + encode(value) { + return JSON.stringify(value); + } + decode(value) { + return JSON.parse(value); + } +}; + +// src/lib/client.ts +var CommonClient = class extends EventEmitter { + address; + rpc_id; + queue; + options; + autoconnect; + ready; + reconnect; + reconnect_timer_id; + reconnect_interval; + max_reconnects; + rest_options; + current_reconnects; + generate_request_id; + socket; + webSocketFactory; + dataPack; + /** + * Instantiate a Client class. + * @constructor + * @param {webSocketFactory} webSocketFactory - factory method for WebSocket + * @param {String} address - url to a websocket server + * @param {Object} options - ws options object with reconnect parameters + * @param {Function} generate_request_id - custom generation request Id + * @param {DataPack} dataPack - data pack contains encoder and decoder + * @return {CommonClient} + */ + constructor(webSocketFactory, address = "ws://localhost:8080", { + autoconnect = true, + reconnect = true, + reconnect_interval = 1e3, + max_reconnects = 5, + ...rest_options + } = {}, generate_request_id, dataPack) { + super(); + this.webSocketFactory = webSocketFactory; + this.queue = {}; + this.rpc_id = 0; + this.address = address; + this.autoconnect = autoconnect; + this.ready = false; + this.reconnect = reconnect; + this.reconnect_timer_id = void 0; + this.reconnect_interval = reconnect_interval; + this.max_reconnects = max_reconnects; + this.rest_options = rest_options; + this.current_reconnects = 0; + this.generate_request_id = generate_request_id || (() => ++this.rpc_id); + if (!dataPack) this.dataPack = new DefaultDataPack(); + else this.dataPack = dataPack; + if (this.autoconnect) + this._connect(this.address, { + autoconnect: this.autoconnect, + reconnect: this.reconnect, + reconnect_interval: this.reconnect_interval, + max_reconnects: this.max_reconnects, + ...this.rest_options + }); + } + /** + * Connects to a defined server if not connected already. + * @method + * @return {Undefined} + */ + connect() { + if (this.socket) return; + this._connect(this.address, { + autoconnect: this.autoconnect, + reconnect: this.reconnect, + reconnect_interval: this.reconnect_interval, + max_reconnects: this.max_reconnects, + ...this.rest_options + }); + } + /** + * Calls a registered RPC method on server. + * @method + * @param {String} method - RPC method name + * @param {Object|Array} params - optional method parameters + * @param {Number} timeout - RPC reply timeout value + * @param {Object} ws_opts - options passed to ws + * @return {Promise} + */ + call(method, params, timeout, ws_opts) { + if (!ws_opts && "object" === typeof timeout) { + ws_opts = timeout; + timeout = null; + } + return new Promise((resolve, reject) => { + if (!this.ready) return reject(new Error("socket not ready")); + const rpc_id = this.generate_request_id(method, params); + const message = { + jsonrpc: "2.0", + method, + params: params || void 0, + id: rpc_id + }; + this.socket.send(this.dataPack.encode(message), ws_opts, (error) => { + if (error) return reject(error); + this.queue[rpc_id] = { promise: [resolve, reject] }; + if (timeout) { + this.queue[rpc_id].timeout = setTimeout(() => { + delete this.queue[rpc_id]; + reject(new Error("reply timeout")); + }, timeout); + } + }); + }); + } + /** + * Logins with the other side of the connection. + * @method + * @param {Object} params - Login credentials object + * @return {Promise} + */ + async login(params) { + const resp = await this.call("rpc.login", params); + if (!resp) throw new Error("authentication failed"); + return resp; + } + /** + * Fetches a list of client's methods registered on server. + * @method + * @return {Array} + */ + async listMethods() { + return await this.call("__listMethods"); + } + /** + * Sends a JSON-RPC 2.0 notification to server. + * @method + * @param {String} method - RPC method name + * @param {Object} params - optional method parameters + * @return {Promise} + */ + notify(method, params) { + return new Promise((resolve, reject) => { + if (!this.ready) return reject(new Error("socket not ready")); + const message = { + jsonrpc: "2.0", + method, + params + }; + this.socket.send(this.dataPack.encode(message), (error) => { + if (error) return reject(error); + resolve(); + }); + }); + } + /** + * Subscribes for a defined event. + * @method + * @param {String|Array} event - event name + * @return {Undefined} + * @throws {Error} + */ + async subscribe(event) { + if (typeof event === "string") event = [event]; + const result = await this.call("rpc.on", event); + if (typeof event === "string" && result[event] !== "ok") + throw new Error( + "Failed subscribing to an event '" + event + "' with: " + result[event] + ); + return result; + } + /** + * Unsubscribes from a defined event. + * @method + * @param {String|Array} event - event name + * @return {Undefined} + * @throws {Error} + */ + async unsubscribe(event) { + if (typeof event === "string") event = [event]; + const result = await this.call("rpc.off", event); + if (typeof event === "string" && result[event] !== "ok") + throw new Error("Failed unsubscribing from an event with: " + result); + return result; + } + /** + * Closes a WebSocket connection gracefully. + * @method + * @param {Number} code - socket close code + * @param {String} data - optional data to be sent before closing + * @return {Undefined} + */ + close(code, data) { + this.socket.close(code || 1e3, data); + } + /** + * Enable / disable automatic reconnection. + * @method + * @param {Boolean} reconnect - enable / disable reconnection + * @return {Undefined} + */ + setAutoReconnect(reconnect) { + this.reconnect = reconnect; + } + /** + * Set the interval between reconnection attempts. + * @method + * @param {Number} interval - reconnection interval in milliseconds + * @return {Undefined} + */ + setReconnectInterval(interval) { + this.reconnect_interval = interval; + } + /** + * Set the maximum number of reconnection attempts. + * @method + * @param {Number} max_reconnects - maximum reconnection attempts + * @return {Undefined} + */ + setMaxReconnects(max_reconnects) { + this.max_reconnects = max_reconnects; + } + /** + * Connection/Message handler. + * @method + * @private + * @param {String} address - WebSocket API address + * @param {Object} options - ws options object + * @return {Undefined} + */ + _connect(address, options) { + clearTimeout(this.reconnect_timer_id); + this.socket = this.webSocketFactory(address, options); + this.socket.addEventListener("open", () => { + this.ready = true; + this.emit("open"); + this.current_reconnects = 0; + }); + this.socket.addEventListener("message", ({ data: message }) => { + if (message instanceof ArrayBuffer) + message = Buffer.from(message).toString(); + try { + message = this.dataPack.decode(message); + } catch (error) { + return; + } + if (message.notification && this.listeners(message.notification).length) { + if (!Object.keys(message.params).length) + return this.emit(message.notification); + const args = [message.notification]; + if (message.params.constructor === Object) args.push(message.params); + else + for (let i = 0; i < message.params.length; i++) + args.push(message.params[i]); + return Promise.resolve().then(() => { + this.emit.apply(this, args); + }); + } + if (!this.queue[message.id]) { + if (message.method) { + return Promise.resolve().then(() => { + this.emit(message.method, message?.params); + }); + } + return; + } + if ("error" in message === "result" in message) + this.queue[message.id].promise[1]( + new Error( + 'Server response malformed. Response must include either "result" or "error", but not both.' + ) + ); + if (this.queue[message.id].timeout) + clearTimeout(this.queue[message.id].timeout); + if (message.error) this.queue[message.id].promise[1](message.error); + else this.queue[message.id].promise[0](message.result); + delete this.queue[message.id]; + }); + this.socket.addEventListener("error", (error) => this.emit("error", error)); + this.socket.addEventListener("close", ({ code, reason }) => { + if (this.ready) + setTimeout(() => this.emit("close", code, reason), 0); + this.ready = false; + this.socket = void 0; + if (code === 1e3) return; + this.current_reconnects++; + if (this.reconnect && (this.max_reconnects > this.current_reconnects || this.max_reconnects === 0)) + this.reconnect_timer_id = setTimeout( + () => this._connect(address, options), + this.reconnect_interval + ); + }); + } +}; +var Server = class extends EventEmitter { + namespaces; + dataPack; + wss; + /** + * Instantiate a Server class. + * @constructor + * @param {Object} options - ws constructor's parameters with rpc + * @param {DataPack} dataPack - data pack contains encoder and decoder + * @return {Server} - returns a new Server instance + */ + constructor(options, dataPack) { + super(); + this.namespaces = {}; + if (!dataPack) this.dataPack = new DefaultDataPack(); + else this.dataPack = dataPack; + this.wss = new WebSocketServer(options); + this.wss.on("listening", () => this.emit("listening")); + this.wss.on("connection", (socket, request) => { + const u = url.parse(request.url, true); + const ns = u.pathname; + if (u.query.socket_id) socket._id = u.query.socket_id; + else socket._id = v1(); + socket["_authenticated"] = false; + socket.on("error", (error) => this.emit("socket-error", socket, error)); + socket.on("close", () => { + this.namespaces[ns].clients.delete(socket._id); + for (const event of Object.keys(this.namespaces[ns].events)) { + const index = this.namespaces[ns].events[event].sockets.indexOf( + socket._id + ); + if (index >= 0) + this.namespaces[ns].events[event].sockets.splice(index, 1); + } + this.emit("disconnection", socket); + }); + if (!this.namespaces[ns]) this._generateNamespace(ns); + this.namespaces[ns].clients.set(socket._id, socket); + this.emit("connection", socket, request); + return this._handleRPC(socket, ns); + }); + this.wss.on("error", (error) => this.emit("error", error)); + } + /** + * Registers an RPC method. + * @method + * @param {String} name - method name + * @param {Function} fn - a callee function + * @param {String} ns - namespace identifier + * @throws {TypeError} + * @return {Object} - returns an IMethod object + */ + register(name, fn, ns = "/") { + if (!this.namespaces[ns]) this._generateNamespace(ns); + this.namespaces[ns].rpc_methods[name] = { + fn, + protected: false + }; + return { + protected: () => this._makeProtectedMethod(name, ns), + public: () => this._makePublicMethod(name, ns) + }; + } + /** + * Sets an auth method. + * @method + * @param {Function} fn - an arbitrary auth method + * @param {String} ns - namespace identifier + * @throws {TypeError} + * @return {Undefined} + */ + setAuth(fn, ns = "/") { + this.register("rpc.login", fn, ns); + } + /** + * Marks an RPC method as protected. + * @method + * @param {String} name - method name + * @param {String} ns - namespace identifier + * @return {Undefined} + */ + _makeProtectedMethod(name, ns = "/") { + this.namespaces[ns].rpc_methods[name].protected = true; + } + /** + * Marks an RPC method as public. + * @method + * @param {String} name - method name + * @param {String} ns - namespace identifier + * @return {Undefined} + */ + _makePublicMethod(name, ns = "/") { + this.namespaces[ns].rpc_methods[name].protected = false; + } + /** + * Marks an event as protected. + * @method + * @param {String} name - event name + * @param {String} ns - namespace identifier + * @return {Undefined} + */ + _makeProtectedEvent(name, ns = "/") { + this.namespaces[ns].events[name].protected = true; + } + /** + * Marks an event as public. + * @method + * @param {String} name - event name + * @param {String} ns - namespace identifier + * @return {Undefined} + */ + _makePublicEvent(name, ns = "/") { + this.namespaces[ns].events[name].protected = false; + } + /** + * Removes a namespace and closes all connections + * @method + * @param {String} ns - namespace identifier + * @throws {TypeError} + * @return {Undefined} + */ + closeNamespace(ns) { + const namespace = this.namespaces[ns]; + if (namespace) { + delete namespace.rpc_methods; + delete namespace.events; + for (const socket of namespace.clients.values()) socket.close(); + delete this.namespaces[ns]; + } + } + /** + * Creates a new event that can be emitted to clients. + * @method + * @param {String} name - event name + * @param {String} ns - namespace identifier + * @throws {TypeError} + * @return {Object} - returns an IEvent object + */ + event(name, ns = "/") { + if (!this.namespaces[ns]) this._generateNamespace(ns); + else { + const index = this.namespaces[ns].events[name]; + if (index !== void 0) + throw new Error(`Already registered event ${ns}${name}`); + } + this.namespaces[ns].events[name] = { + sockets: [], + protected: false + }; + this.on(name, (...params) => { + if (params.length === 1 && params[0] instanceof Object) + params = params[0]; + for (const socket_id of this.namespaces[ns].events[name].sockets) { + const socket = this.namespaces[ns].clients.get(socket_id); + if (!socket) continue; + socket.send( + this.dataPack.encode({ + notification: name, + params + }) + ); + } + }); + return { + protected: () => this._makeProtectedEvent(name, ns), + public: () => this._makePublicEvent(name, ns) + }; + } + /** + * Returns a requested namespace object + * @method + * @param {String} name - namespace identifier + * @throws {TypeError} + * @return {Object} - namespace object + */ + of(name) { + if (!this.namespaces[name]) this._generateNamespace(name); + const self = this; + return { + // self.register convenience method + register(fn_name, fn) { + if (arguments.length !== 2) + throw new Error("must provide exactly two arguments"); + if (typeof fn_name !== "string") + throw new Error("name must be a string"); + if (typeof fn !== "function") + throw new Error("handler must be a function"); + return self.register(fn_name, fn, name); + }, + // self.event convenience method + event(ev_name) { + if (arguments.length !== 1) + throw new Error("must provide exactly one argument"); + if (typeof ev_name !== "string") + throw new Error("name must be a string"); + return self.event(ev_name, name); + }, + // self.eventList convenience method + get eventList() { + return Object.keys(self.namespaces[name].events); + }, + /** + * Emits a specified event to this namespace. + * @inner + * @method + * @param {String} event - event name + * @param {Array} params - event parameters + * @return {Undefined} + */ + emit(event, ...params) { + const socket_ids = [...self.namespaces[name].clients.keys()]; + for (let i = 0, id; id = socket_ids[i]; ++i) { + self.namespaces[name].clients.get(id).send( + self.dataPack.encode({ + notification: event, + params: params || [] + }) + ); + } + }, + /** + * Returns a name of this namespace. + * @inner + * @method + * @kind constant + * @return {String} + */ + get name() { + return name; + }, + /** + * Returns a hash of websocket objects connected to this namespace. + * @inner + * @method + * @return {Object} + */ + connected() { + const socket_ids = [...self.namespaces[name].clients.keys()]; + return socket_ids.reduce( + (acc, curr) => ({ + ...acc, + [curr]: self.namespaces[name].clients.get(curr) + }), + {} + ); + }, + /** + * Returns a list of client unique identifiers connected to this namespace. + * @inner + * @method + * @return {Array} + */ + clients() { + return self.namespaces[name]; + } + }; + } + /** + * Lists all created events in a given namespace. Defaults to "/". + * @method + * @param {String} ns - namespaces identifier + * @readonly + * @return {Array} - returns a list of created events + */ + eventList(ns = "/") { + if (!this.namespaces[ns]) return []; + return Object.keys(this.namespaces[ns].events); + } + /** + * Creates a JSON-RPC 2.0 compliant error + * @method + * @param {Number} code - indicates the error type that occurred + * @param {String} message - provides a short description of the error + * @param {String|Object} data - details containing additional information about the error + * @return {Object} + */ + createError(code, message, data) { + return { + code, + message, + data: data || null + }; + } + /** + * Closes the server and terminates all clients. + * @method + * @return {Promise} + */ + close() { + return new Promise((resolve, reject) => { + try { + this.wss.close(); + this.emit("close"); + resolve(); + } catch (error) { + reject(error); + } + }); + } + /** + * Handles all WebSocket JSON RPC 2.0 requests. + * @private + * @param {Object} socket - ws socket instance + * @param {String} ns - namespaces identifier + * @return {Undefined} + */ + _handleRPC(socket, ns = "/") { + socket.on("message", async (data) => { + const msg_options = {}; + if (data instanceof ArrayBuffer) { + msg_options.binary = true; + data = Buffer.from(data).toString(); + } + if (socket.readyState !== 1) return; + let parsedData; + try { + parsedData = this.dataPack.decode(data); + } catch (error) { + return socket.send( + this.dataPack.encode({ + jsonrpc: "2.0", + error: createError(-32700, error.toString()), + id: null + }), + msg_options + ); + } + if (Array.isArray(parsedData)) { + if (!parsedData.length) + return socket.send( + this.dataPack.encode({ + jsonrpc: "2.0", + error: createError(-32600, "Invalid array"), + id: null + }), + msg_options + ); + const responses = []; + for (const message of parsedData) { + const response2 = await this._runMethod(message, socket._id, ns); + if (!response2) continue; + responses.push(response2); + } + if (!responses.length) return; + return socket.send(this.dataPack.encode(responses), msg_options); + } + const response = await this._runMethod(parsedData, socket._id, ns); + if (!response) return; + return socket.send(this.dataPack.encode(response), msg_options); + }); + } + /** + * Runs a defined RPC method. + * @private + * @param {Object} message - a message received + * @param {Object} socket_id - user's socket id + * @param {String} ns - namespaces identifier + * @return {Object|undefined} + */ + async _runMethod(message, socket_id, ns = "/") { + if (typeof message !== "object" || message === null) + return { + jsonrpc: "2.0", + error: createError(-32600), + id: null + }; + if (message.jsonrpc !== "2.0") + return { + jsonrpc: "2.0", + error: createError(-32600, "Invalid JSON RPC version"), + id: message.id || null + }; + if (!message.method) + return { + jsonrpc: "2.0", + error: createError(-32602, "Method not specified"), + id: message.id || null + }; + if (typeof message.method !== "string") + return { + jsonrpc: "2.0", + error: createError(-32600, "Invalid method name"), + id: message.id || null + }; + if (message.params && typeof message.params === "string") + return { + jsonrpc: "2.0", + error: createError(-32600), + id: message.id || null + }; + if (message.method === "rpc.on") { + if (!message.params) + return { + jsonrpc: "2.0", + error: createError(-32e3), + id: message.id || null + }; + const results = {}; + const event_names = Object.keys(this.namespaces[ns].events); + for (const name of message.params) { + const index = event_names.indexOf(name); + const namespace = this.namespaces[ns]; + if (index === -1) { + results[name] = "provided event invalid"; + continue; + } + if (namespace.events[event_names[index]].protected === true && namespace.clients.get(socket_id)["_authenticated"] === false) { + return { + jsonrpc: "2.0", + error: createError(-32606), + id: message.id || null + }; + } + const socket_index = namespace.events[event_names[index]].sockets.indexOf(socket_id); + if (socket_index >= 0) { + results[name] = "socket has already been subscribed to event"; + continue; + } + namespace.events[event_names[index]].sockets.push(socket_id); + results[name] = "ok"; + } + return { + jsonrpc: "2.0", + result: results, + id: message.id || null + }; + } else if (message.method === "rpc.off") { + if (!message.params) + return { + jsonrpc: "2.0", + error: createError(-32e3), + id: message.id || null + }; + const results = {}; + for (const name of message.params) { + if (!this.namespaces[ns].events[name]) { + results[name] = "provided event invalid"; + continue; + } + const index = this.namespaces[ns].events[name].sockets.indexOf(socket_id); + if (index === -1) { + results[name] = "not subscribed"; + continue; + } + this.namespaces[ns].events[name].sockets.splice(index, 1); + results[name] = "ok"; + } + return { + jsonrpc: "2.0", + result: results, + id: message.id || null + }; + } else if (message.method === "rpc.login") { + if (!message.params) + return { + jsonrpc: "2.0", + error: createError(-32604), + id: message.id || null + }; + } + if (!this.namespaces[ns].rpc_methods[message.method]) { + return { + jsonrpc: "2.0", + error: createError(-32601), + id: message.id || null + }; + } + let response = null; + if (this.namespaces[ns].rpc_methods[message.method].protected === true && this.namespaces[ns].clients.get(socket_id)["_authenticated"] === false) { + return { + jsonrpc: "2.0", + error: createError(-32605), + id: message.id || null + }; + } + try { + response = await this.namespaces[ns].rpc_methods[message.method].fn( + message.params, + socket_id + ); + } catch (error) { + if (!message.id) return; + if (error instanceof Error) + return { + jsonrpc: "2.0", + error: { + code: -32e3, + message: error.name, + data: error.message + }, + id: message.id + }; + return { + jsonrpc: "2.0", + error, + id: message.id + }; + } + if (!message.id) return; + if (message.method === "rpc.login" && response === true) { + const s = this.namespaces[ns].clients.get(socket_id); + s["_authenticated"] = true; + this.namespaces[ns].clients.set(socket_id, s); + } + return { + jsonrpc: "2.0", + result: response, + id: message.id + }; + } + /** + * Generate a new namespace store. + * Also preregister some special namespace methods. + * @private + * @param {String} name - namespaces identifier + * @return {undefined} + */ + _generateNamespace(name) { + this.namespaces[name] = { + rpc_methods: { + __listMethods: { + fn: () => Object.keys(this.namespaces[name].rpc_methods), + protected: false + } + }, + clients: /* @__PURE__ */ new Map(), + events: {} + }; + } +}; +var RPC_ERRORS = /* @__PURE__ */ new Map([ + [-32e3, "Event not provided"], + [-32600, "Invalid Request"], + [-32601, "Method not found"], + [-32602, "Invalid params"], + [-32603, "Internal error"], + [-32604, "Params not found"], + [-32605, "Method forbidden"], + [-32606, "Event forbidden"], + [-32700, "Parse error"] +]); +function createError(code, details) { + const error = { + code, + message: RPC_ERRORS.get(code) || "Internal Server Error" + }; + if (details) error["data"] = details; + return error; +} + +// src/index.ts +var Client = class extends CommonClient { + constructor(address = "ws://localhost:8080", { + autoconnect = true, + reconnect = true, + reconnect_interval = 1e3, + max_reconnects = 5, + ...rest_options + } = {}, generate_request_id) { + super( + WebSocket, + address, + { + autoconnect, + reconnect, + reconnect_interval, + max_reconnects, + ...rest_options + }, + generate_request_id + ); + } +}; + +export { Client, CommonClient, DefaultDataPack, Server, WebSocket, createError }; +//# sourceMappingURL=out.js.map +//# sourceMappingURL=index.mjs.map \ No newline at end of file diff --git a/dist/index.mjs.map b/dist/index.mjs.map new file mode 100644 index 0000000..6e99d14 --- /dev/null +++ b/dist/index.mjs.map @@ -0,0 +1 @@ +{"version":3,"sources":["../src/lib/client/websocket.ts","../src/lib/client.ts","../src/lib/utils.ts","../src/lib/server.ts","../src/index.ts"],"names":["EventEmitter","response"],"mappings":"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","sourcesContent":["/* A wrapper for the \"qaap/uws-bindings\" library. */\n\n\"use strict\"\n\nimport WebSocketImpl from \"ws\"\n\nimport { IWSClientAdditionalOptions } from \"./client.types.js\"\n\n/**\n * factory method for common WebSocket instance\n * @method\n * @param {String} address - url to a websocket server\n * @param {(Object)} options - websocket options\n * @return {Undefined}\n */\nexport function WebSocket(\n address: string,\n options: IWSClientAdditionalOptions & WebSocketImpl.ClientOptions\n)\n{\n return new WebSocketImpl(address, options)\n}\n","/**\n * \"Client\" wraps \"ws\" or a browser-implemented \"WebSocket\" library\n * according to the environment providing JSON RPC 2.0 support on top.\n * @module Client\n */\n\n\"use strict\"\n\nimport NodeWebSocket from \"ws\"\nimport { EventEmitter } from \"eventemitter3\"\nimport {\n ICommonWebSocket,\n IWSClientAdditionalOptions,\n NodeWebSocketType,\n ICommonWebSocketFactory,\n} from \"./client/client.types.js\"\n\nimport { DataPack, DefaultDataPack } from \"./utils.js\"\n\ninterface IQueueElement {\n promise: [\n Parameters[0]>[0],\n Parameters[0]>[1]\n ];\n timeout?: ReturnType;\n}\n\nexport interface IQueue {\n [x: number]: IQueueElement;\n}\n\nexport interface IWSRequestParams {\n [x: string]: any;\n [x: number]: any;\n}\n\nexport class CommonClient extends EventEmitter\n{\n private address: string\n private rpc_id: number\n private queue: IQueue\n private options: IWSClientAdditionalOptions & NodeWebSocket.ClientOptions\n private autoconnect: boolean\n private ready: boolean\n private reconnect: boolean\n private reconnect_timer_id: NodeJS.Timeout\n private reconnect_interval: number\n private max_reconnects: number\n private rest_options: IWSClientAdditionalOptions &\n NodeWebSocket.ClientOptions\n private current_reconnects: number\n private generate_request_id: (\n method: string,\n params: object | Array\n ) => number\n private socket: ICommonWebSocket\n private webSocketFactory: ICommonWebSocketFactory\n private dataPack: DataPack\n\n /**\n * Instantiate a Client class.\n * @constructor\n * @param {webSocketFactory} webSocketFactory - factory method for WebSocket\n * @param {String} address - url to a websocket server\n * @param {Object} options - ws options object with reconnect parameters\n * @param {Function} generate_request_id - custom generation request Id\n * @param {DataPack} dataPack - data pack contains encoder and decoder\n * @return {CommonClient}\n */\n constructor(\n webSocketFactory: ICommonWebSocketFactory,\n address = \"ws://localhost:8080\",\n {\n autoconnect = true,\n reconnect = true,\n reconnect_interval = 1000,\n max_reconnects = 5,\n ...rest_options\n } = {},\n generate_request_id?: (\n method: string,\n params: object | Array\n ) => number,\n dataPack?: DataPack\n )\n {\n super()\n\n this.webSocketFactory = webSocketFactory\n\n this.queue = {}\n this.rpc_id = 0\n\n this.address = address\n this.autoconnect = autoconnect\n this.ready = false\n this.reconnect = reconnect\n this.reconnect_timer_id = undefined\n this.reconnect_interval = reconnect_interval\n this.max_reconnects = max_reconnects\n this.rest_options = rest_options\n this.current_reconnects = 0\n this.generate_request_id = generate_request_id || (() => ++this.rpc_id)\n\n if (!dataPack) this.dataPack = new DefaultDataPack()\n else this.dataPack = dataPack\n\n if (this.autoconnect)\n this._connect(this.address, {\n autoconnect: this.autoconnect,\n reconnect: this.reconnect,\n reconnect_interval: this.reconnect_interval,\n max_reconnects: this.max_reconnects,\n ...this.rest_options,\n })\n }\n\n /**\n * Connects to a defined server if not connected already.\n * @method\n * @return {Undefined}\n */\n connect()\n {\n if (this.socket) return\n\n this._connect(this.address, {\n autoconnect: this.autoconnect,\n reconnect: this.reconnect,\n reconnect_interval: this.reconnect_interval,\n max_reconnects: this.max_reconnects,\n ...this.rest_options,\n })\n }\n\n /**\n * Calls a registered RPC method on server.\n * @method\n * @param {String} method - RPC method name\n * @param {Object|Array} params - optional method parameters\n * @param {Number} timeout - RPC reply timeout value\n * @param {Object} ws_opts - options passed to ws\n * @return {Promise}\n */\n call(\n method: string,\n params?: IWSRequestParams,\n timeout?: number,\n ws_opts?: Parameters[1]\n )\n {\n if (!ws_opts && \"object\" === typeof timeout)\n {\n ws_opts = timeout\n timeout = null\n }\n\n return new Promise((resolve, reject) =>\n {\n if (!this.ready) return reject(new Error(\"socket not ready\"))\n\n const rpc_id = this.generate_request_id(method, params)\n\n const message = {\n jsonrpc: \"2.0\",\n method: method,\n params: params || undefined,\n id: rpc_id,\n }\n\n this.socket.send(this.dataPack.encode(message), ws_opts, (error) =>\n {\n if (error) return reject(error)\n\n this.queue[rpc_id] = { promise: [resolve, reject] }\n\n if (timeout)\n {\n this.queue[rpc_id].timeout = setTimeout(() =>\n {\n delete this.queue[rpc_id]\n reject(new Error(\"reply timeout\"))\n }, timeout)\n }\n })\n })\n }\n\n /**\n * Logins with the other side of the connection.\n * @method\n * @param {Object} params - Login credentials object\n * @return {Promise}\n */\n async login(params: IWSRequestParams)\n {\n const resp = await this.call(\"rpc.login\", params)\n\n if (!resp) throw new Error(\"authentication failed\")\n\n return resp\n }\n\n /**\n * Fetches a list of client's methods registered on server.\n * @method\n * @return {Array}\n */\n async listMethods()\n {\n return await this.call(\"__listMethods\")\n }\n\n /**\n * Sends a JSON-RPC 2.0 notification to server.\n * @method\n * @param {String} method - RPC method name\n * @param {Object} params - optional method parameters\n * @return {Promise}\n */\n notify(method: string, params?: IWSRequestParams)\n {\n return new Promise((resolve, reject) =>\n {\n if (!this.ready) return reject(new Error(\"socket not ready\"))\n\n const message = {\n jsonrpc: \"2.0\",\n method: method,\n params,\n }\n\n this.socket.send(this.dataPack.encode(message), (error) =>\n {\n if (error) return reject(error)\n\n resolve()\n })\n })\n }\n\n /**\n * Subscribes for a defined event.\n * @method\n * @param {String|Array} event - event name\n * @return {Undefined}\n * @throws {Error}\n */\n async subscribe(event: string | Array)\n {\n if (typeof event === \"string\") event = [event]\n\n const result = await this.call(\"rpc.on\", event)\n\n if (typeof event === \"string\" && result[event] !== \"ok\")\n throw new Error(\n \"Failed subscribing to an event '\" + event + \"' with: \" + result[event]\n )\n\n return result\n }\n\n /**\n * Unsubscribes from a defined event.\n * @method\n * @param {String|Array} event - event name\n * @return {Undefined}\n * @throws {Error}\n */\n async unsubscribe(event: string | Array)\n {\n if (typeof event === \"string\") event = [event]\n\n const result = await this.call(\"rpc.off\", event)\n\n if (typeof event === \"string\" && result[event] !== \"ok\")\n throw new Error(\"Failed unsubscribing from an event with: \" + result)\n\n return result\n }\n\n /**\n * Closes a WebSocket connection gracefully.\n * @method\n * @param {Number} code - socket close code\n * @param {String} data - optional data to be sent before closing\n * @return {Undefined}\n */\n close(code?: number, data?: string)\n {\n this.socket.close(code || 1000, data)\n }\n\n /**\n * Enable / disable automatic reconnection.\n * @method\n * @param {Boolean} reconnect - enable / disable reconnection\n * @return {Undefined}\n */\n setAutoReconnect(reconnect: boolean)\n {\n this.reconnect = reconnect\n }\n\n /**\n * Set the interval between reconnection attempts.\n * @method\n * @param {Number} interval - reconnection interval in milliseconds\n * @return {Undefined}\n */\n setReconnectInterval(interval: number)\n {\n this.reconnect_interval = interval\n }\n\n /**\n * Set the maximum number of reconnection attempts.\n * @method\n * @param {Number} max_reconnects - maximum reconnection attempts\n * @return {Undefined}\n */\n setMaxReconnects(max_reconnects: number)\n {\n this.max_reconnects = max_reconnects\n }\n\n /**\n * Connection/Message handler.\n * @method\n * @private\n * @param {String} address - WebSocket API address\n * @param {Object} options - ws options object\n * @return {Undefined}\n */\n private _connect(\n address: string,\n options: IWSClientAdditionalOptions & NodeWebSocket.ClientOptions\n )\n {\n clearTimeout(this.reconnect_timer_id)\n this.socket = this.webSocketFactory(address, options)\n\n this.socket.addEventListener(\"open\", () =>\n {\n this.ready = true\n this.emit(\"open\")\n this.current_reconnects = 0\n })\n\n this.socket.addEventListener(\"message\", ({ data: message }) =>\n {\n if (message instanceof ArrayBuffer)\n message = Buffer.from(message).toString()\n\n try\n {\n message = this.dataPack.decode(message)\n }\n catch (error)\n {\n return\n }\n\n // check if any listeners are attached and forward event\n if (message.notification && this.listeners(message.notification).length)\n {\n if (!Object.keys(message.params).length)\n return this.emit(message.notification)\n\n const args = [message.notification]\n\n if (message.params.constructor === Object) args.push(message.params)\n // using for-loop instead of unshift/spread because performance is better\n else\n for (let i = 0; i < message.params.length; i++)\n args.push(message.params[i])\n\n // run as microtask so that pending queue messages are resolved first\n // eslint-disable-next-line prefer-spread\n return Promise.resolve().then(() =>\n {\n // eslint-disable-next-line prefer-spread\n this.emit.apply(this, args)\n })\n }\n\n if (!this.queue[message.id])\n {\n // general JSON RPC 2.0 events\n if (message.method)\n {\n // run as microtask so that pending queue messages are resolved first\n return Promise.resolve().then(() =>\n {\n this.emit(message.method, message?.params)\n })\n }\n\n return\n }\n\n // reject early since server's response is invalid\n if (\"error\" in message === \"result\" in message)\n this.queue[message.id].promise[1](\n new Error(\n \"Server response malformed. Response must include either \\\"result\\\"\" +\n \" or \\\"error\\\", but not both.\"\n )\n )\n\n if (this.queue[message.id].timeout)\n clearTimeout(this.queue[message.id].timeout)\n\n if (message.error) this.queue[message.id].promise[1](message.error)\n else this.queue[message.id].promise[0](message.result)\n\n delete this.queue[message.id]\n })\n\n this.socket.addEventListener(\"error\", (error) => this.emit(\"error\", error))\n\n this.socket.addEventListener(\"close\", ({ code, reason }) =>\n {\n if (this.ready)\n // Delay close event until internal state is updated\n setTimeout(() => this.emit(\"close\", code, reason), 0)\n\n this.ready = false\n this.socket = undefined\n\n if (code === 1000) return\n\n this.current_reconnects++\n\n if (\n this.reconnect &&\n (this.max_reconnects > this.current_reconnects ||\n this.max_reconnects === 0)\n )\n this.reconnect_timer_id = setTimeout(\n () => this._connect(address, options),\n this.reconnect_interval\n )\n })\n }\n}\n","\"use strict\"\n\nexport interface DataPack<\n T,\n R extends string | ArrayBufferLike | Blob | ArrayBufferView\n> {\n encode(value: T): R;\n decode(value: R): T;\n}\n\nexport class DefaultDataPack implements DataPack\n{\n encode(value: Object): string\n {\n return JSON.stringify(value)\n }\n\n decode(value: string): Object\n {\n return JSON.parse(value)\n }\n}\n","/**\n * \"Server\" wraps the \"ws\" library providing JSON RPC 2.0 support on top.\n * @module Server\n */\n\n\"use strict\"\n\nimport { EventEmitter } from \"eventemitter3\"\nimport url from \"node:url\"\nimport { v1 as uuidv1 } from \"uuid\"\nimport NodeWebSocket, { WebSocketServer } from \"ws\"\n\nimport { DataPack, DefaultDataPack } from \"./utils.js\"\n\ninterface INamespaceEvent {\n [x: string]: {\n sockets: Array;\n protected: boolean;\n };\n}\n\ninterface IMethod {\n public: () => void;\n protected: () => void;\n}\n\ninterface IEvent {\n public: () => void;\n protected: () => void;\n}\n\ninterface IRPCError {\n code: number;\n message: string;\n data?: string;\n}\n\ninterface IRPCMethodParams {\n [x: string]: any;\n}\n\ninterface IRPCMethod {\n [x: string]: {\n fn: (params: IRPCMethodParams, socket_id: string) => any;\n protected: boolean;\n };\n}\n\ninterface INamespace {\n [x: string]: {\n rpc_methods: IRPCMethod;\n clients: Map;\n events: INamespaceEvent;\n };\n}\n\ninterface IClientWebSocket extends NodeWebSocket {\n _id: string;\n _authenticated: boolean;\n}\n\ninterface IRPCResult {\n [x: string]: string;\n}\n\nexport class Server extends EventEmitter\n{\n private namespaces: INamespace\n private dataPack: DataPack\n wss: InstanceType\n\n /**\n * Instantiate a Server class.\n * @constructor\n * @param {Object} options - ws constructor's parameters with rpc\n * @param {DataPack} dataPack - data pack contains encoder and decoder\n * @return {Server} - returns a new Server instance\n */\n constructor(\n options: NodeWebSocket.ServerOptions,\n dataPack?: DataPack\n )\n {\n super()\n\n /**\n * Stores all connected sockets with a universally unique identifier\n * in the appropriate namespace.\n * Stores all rpc methods to specific namespaces. \"/\" by default.\n * Stores all events as keys and subscribed users in array as value\n * @private\n * @name namespaces\n * @param {Object} namespaces.rpc_methods\n * @param {Map} namespaces.clients\n * @param {Object} namespaces.events\n */\n this.namespaces = {}\n\n if (!dataPack) this.dataPack = new DefaultDataPack()\n else this.dataPack = dataPack\n\n this.wss = new WebSocketServer(options)\n\n this.wss.on(\"listening\", () => this.emit(\"listening\"))\n\n this.wss.on(\"connection\", (socket: IClientWebSocket, request) =>\n {\n const u = url.parse(request.url, true)\n const ns = u.pathname\n\n if (u.query.socket_id) socket._id = u.query.socket_id as string\n else socket._id = uuidv1()\n\n // unauthenticated by default\n socket[\"_authenticated\"] = false\n\n // propagate socket errors\n socket.on(\"error\", (error) => this.emit(\"socket-error\", socket, error))\n\n // cleanup after the socket gets disconnected\n socket.on(\"close\", () =>\n {\n this.namespaces[ns].clients.delete(socket._id)\n\n for (const event of Object.keys(this.namespaces[ns].events))\n {\n const index = this.namespaces[ns].events[event].sockets.indexOf(\n socket._id\n )\n\n if (index >= 0)\n this.namespaces[ns].events[event].sockets.splice(index, 1)\n }\n\n this.emit(\"disconnection\", socket)\n })\n\n if (!this.namespaces[ns]) this._generateNamespace(ns)\n\n // store socket and method\n this.namespaces[ns].clients.set(socket._id, socket)\n\n this.emit(\"connection\", socket, request)\n\n return this._handleRPC(socket, ns)\n })\n\n this.wss.on(\"error\", (error) => this.emit(\"error\", error))\n }\n\n /**\n * Registers an RPC method.\n * @method\n * @param {String} name - method name\n * @param {Function} fn - a callee function\n * @param {String} ns - namespace identifier\n * @throws {TypeError}\n * @return {Object} - returns an IMethod object\n */\n register(\n name: string,\n fn: (params: IRPCMethodParams, socket_id: string) => void,\n ns = \"/\"\n )\n {\n if (!this.namespaces[ns]) this._generateNamespace(ns)\n\n this.namespaces[ns].rpc_methods[name] = {\n fn: fn,\n protected: false,\n }\n\n return {\n protected: () => this._makeProtectedMethod(name, ns),\n public: () => this._makePublicMethod(name, ns),\n } as IMethod\n }\n\n /**\n * Sets an auth method.\n * @method\n * @param {Function} fn - an arbitrary auth method\n * @param {String} ns - namespace identifier\n * @throws {TypeError}\n * @return {Undefined}\n */\n setAuth(\n fn: (params: IRPCMethodParams, socket_id: string) => Promise,\n ns = \"/\"\n )\n {\n this.register(\"rpc.login\", fn, ns)\n }\n\n /**\n * Marks an RPC method as protected.\n * @method\n * @param {String} name - method name\n * @param {String} ns - namespace identifier\n * @return {Undefined}\n */\n private _makeProtectedMethod(name: string, ns = \"/\")\n {\n this.namespaces[ns].rpc_methods[name].protected = true\n }\n\n /**\n * Marks an RPC method as public.\n * @method\n * @param {String} name - method name\n * @param {String} ns - namespace identifier\n * @return {Undefined}\n */\n private _makePublicMethod(name: string, ns = \"/\")\n {\n this.namespaces[ns].rpc_methods[name].protected = false\n }\n\n /**\n * Marks an event as protected.\n * @method\n * @param {String} name - event name\n * @param {String} ns - namespace identifier\n * @return {Undefined}\n */\n private _makeProtectedEvent(name: string, ns = \"/\")\n {\n this.namespaces[ns].events[name].protected = true\n }\n\n /**\n * Marks an event as public.\n * @method\n * @param {String} name - event name\n * @param {String} ns - namespace identifier\n * @return {Undefined}\n */\n private _makePublicEvent(name: string, ns = \"/\")\n {\n this.namespaces[ns].events[name].protected = false\n }\n\n /**\n * Removes a namespace and closes all connections\n * @method\n * @param {String} ns - namespace identifier\n * @throws {TypeError}\n * @return {Undefined}\n */\n closeNamespace(ns: string)\n {\n const namespace = this.namespaces[ns]\n\n if (namespace)\n {\n delete namespace.rpc_methods\n delete namespace.events\n\n for (const socket of namespace.clients.values()) socket.close()\n\n delete this.namespaces[ns]\n }\n }\n\n /**\n * Creates a new event that can be emitted to clients.\n * @method\n * @param {String} name - event name\n * @param {String} ns - namespace identifier\n * @throws {TypeError}\n * @return {Object} - returns an IEvent object\n */\n event(name: string, ns = \"/\"): IEvent\n {\n if (!this.namespaces[ns]) this._generateNamespace(ns)\n else\n {\n const index = this.namespaces[ns].events[name]\n\n if (index !== undefined)\n throw new Error(`Already registered event ${ns}${name}`)\n }\n\n this.namespaces[ns].events[name] = {\n sockets: [],\n protected: false,\n }\n\n // forward emitted event to subscribers\n this.on(name, (...params) =>\n {\n // flatten an object if no spreading is wanted\n if (params.length === 1 && params[0] instanceof Object)\n params = params[0]\n\n for (const socket_id of this.namespaces[ns].events[name].sockets)\n {\n const socket = this.namespaces[ns].clients.get(socket_id)\n\n if (!socket) continue\n\n socket.send(\n this.dataPack.encode({\n notification: name,\n params,\n })\n )\n }\n })\n\n return {\n protected: () => this._makeProtectedEvent(name, ns),\n public: () => this._makePublicEvent(name, ns),\n }\n }\n\n /**\n * Returns a requested namespace object\n * @method\n * @param {String} name - namespace identifier\n * @throws {TypeError}\n * @return {Object} - namespace object\n */\n of(name: string)\n {\n if (!this.namespaces[name]) this._generateNamespace(name)\n\n const self = this\n\n return {\n // self.register convenience method\n register(\n fn_name: string,\n fn: (params: IRPCMethodParams) => void\n ): IMethod\n {\n if (arguments.length !== 2)\n throw new Error(\"must provide exactly two arguments\")\n\n if (typeof fn_name !== \"string\")\n throw new Error(\"name must be a string\")\n\n if (typeof fn !== \"function\")\n throw new Error(\"handler must be a function\")\n\n return self.register(fn_name, fn, name)\n },\n\n // self.event convenience method\n event(ev_name: string): IEvent\n {\n if (arguments.length !== 1)\n throw new Error(\"must provide exactly one argument\")\n\n if (typeof ev_name !== \"string\")\n throw new Error(\"name must be a string\")\n\n return self.event(ev_name, name)\n },\n\n // self.eventList convenience method\n get eventList()\n {\n return Object.keys(self.namespaces[name].events)\n },\n\n /**\n * Emits a specified event to this namespace.\n * @inner\n * @method\n * @param {String} event - event name\n * @param {Array} params - event parameters\n * @return {Undefined}\n */\n emit(event: string, ...params: Array)\n {\n const socket_ids = [...self.namespaces[name].clients.keys()]\n\n for (let i = 0, id; (id = socket_ids[i]); ++i)\n {\n self.namespaces[name].clients.get(id).send(\n self.dataPack.encode({\n notification: event,\n params: params || [],\n })\n )\n }\n },\n\n /**\n * Returns a name of this namespace.\n * @inner\n * @method\n * @kind constant\n * @return {String}\n */\n get name()\n {\n return name\n },\n\n /**\n * Returns a hash of websocket objects connected to this namespace.\n * @inner\n * @method\n * @return {Object}\n */\n connected()\n {\n const socket_ids = [...self.namespaces[name].clients.keys()]\n\n return socket_ids.reduce(\n (acc, curr) => ({\n ...acc,\n [curr]: self.namespaces[name].clients.get(curr),\n }),\n {}\n )\n },\n\n /**\n * Returns a list of client unique identifiers connected to this namespace.\n * @inner\n * @method\n * @return {Array}\n */\n clients()\n {\n return self.namespaces[name]\n },\n }\n }\n\n /**\n * Lists all created events in a given namespace. Defaults to \"/\".\n * @method\n * @param {String} ns - namespaces identifier\n * @readonly\n * @return {Array} - returns a list of created events\n */\n eventList(ns = \"/\")\n {\n if (!this.namespaces[ns]) return []\n\n return Object.keys(this.namespaces[ns].events)\n }\n\n /**\n * Creates a JSON-RPC 2.0 compliant error\n * @method\n * @param {Number} code - indicates the error type that occurred\n * @param {String} message - provides a short description of the error\n * @param {String|Object} data - details containing additional information about the error\n * @return {Object}\n */\n createError(code: number, message: string, data: string | object)\n {\n return {\n code: code,\n message: message,\n data: data || null,\n }\n }\n\n /**\n * Closes the server and terminates all clients.\n * @method\n * @return {Promise}\n */\n close()\n {\n return new Promise((resolve, reject) =>\n {\n try\n {\n this.wss.close()\n this.emit(\"close\")\n resolve()\n }\n catch (error)\n {\n reject(error)\n }\n })\n }\n\n /**\n * Handles all WebSocket JSON RPC 2.0 requests.\n * @private\n * @param {Object} socket - ws socket instance\n * @param {String} ns - namespaces identifier\n * @return {Undefined}\n */\n private _handleRPC(socket: IClientWebSocket, ns = \"/\")\n {\n socket.on(\"message\", async (data: any) =>\n {\n const msg_options: Parameters[1] = {}\n\n if (data instanceof ArrayBuffer)\n {\n msg_options.binary = true\n\n data = Buffer.from(data).toString()\n }\n\n if (socket.readyState !== 1) return // TODO: should have debug logs here\n\n let parsedData: any\n\n try\n {\n parsedData = this.dataPack.decode(data as string)\n }\n catch (error)\n {\n return socket.send(\n this.dataPack.encode({\n jsonrpc: \"2.0\",\n error: createError(-32700, error.toString()),\n id: null,\n }),\n msg_options\n )\n }\n\n if (Array.isArray(parsedData))\n {\n if (!parsedData.length)\n return socket.send(\n this.dataPack.encode({\n jsonrpc: \"2.0\",\n error: createError(-32600, \"Invalid array\"),\n id: null,\n }),\n msg_options\n )\n\n const responses = []\n\n for (const message of parsedData)\n {\n const response = await this._runMethod(message, socket._id, ns)\n\n if (!response) continue\n\n responses.push(response)\n }\n\n if (!responses.length) return\n\n return socket.send(this.dataPack.encode(responses), msg_options)\n }\n\n const response = await this._runMethod(parsedData, socket._id, ns)\n\n if (!response) return\n\n return socket.send(this.dataPack.encode(response), msg_options)\n })\n }\n\n /**\n * Runs a defined RPC method.\n * @private\n * @param {Object} message - a message received\n * @param {Object} socket_id - user's socket id\n * @param {String} ns - namespaces identifier\n * @return {Object|undefined}\n */\n private async _runMethod(message: any, socket_id: string, ns = \"/\")\n {\n if (typeof message !== \"object\" || message === null)\n return {\n jsonrpc: \"2.0\",\n error: createError(-32600),\n id: null,\n }\n\n if (message.jsonrpc !== \"2.0\")\n return {\n jsonrpc: \"2.0\",\n error: createError(-32600, \"Invalid JSON RPC version\"),\n id: message.id || null,\n }\n\n if (!message.method)\n return {\n jsonrpc: \"2.0\",\n error: createError(-32602, \"Method not specified\"),\n id: message.id || null,\n }\n\n if (typeof message.method !== \"string\")\n return {\n jsonrpc: \"2.0\",\n error: createError(-32600, \"Invalid method name\"),\n id: message.id || null,\n }\n\n if (message.params && typeof message.params === \"string\")\n return {\n jsonrpc: \"2.0\",\n error: createError(-32600),\n id: message.id || null,\n }\n\n if (message.method === \"rpc.on\")\n {\n if (!message.params)\n return {\n jsonrpc: \"2.0\",\n error: createError(-32000),\n id: message.id || null,\n }\n\n const results: IRPCMethodParams = {}\n\n const event_names = Object.keys(this.namespaces[ns].events)\n\n for (const name of message.params)\n {\n const index = event_names.indexOf(name)\n const namespace = this.namespaces[ns]\n\n if (index === -1)\n {\n results[name] = \"provided event invalid\"\n continue\n }\n\n // reject request if event is protected and if client is not authenticated\n if (\n namespace.events[event_names[index]].protected === true &&\n namespace.clients.get(socket_id)[\"_authenticated\"] === false\n )\n {\n return {\n jsonrpc: \"2.0\",\n error: createError(-32606),\n id: message.id || null,\n }\n }\n\n const socket_index =\n namespace.events[event_names[index]].sockets.indexOf(socket_id)\n if (socket_index >= 0)\n {\n results[name] = \"socket has already been subscribed to event\"\n continue\n }\n namespace.events[event_names[index]].sockets.push(socket_id)\n\n results[name] = \"ok\"\n }\n\n return {\n jsonrpc: \"2.0\",\n result: results,\n id: message.id || null,\n }\n }\n else if (message.method === \"rpc.off\")\n {\n if (!message.params)\n return {\n jsonrpc: \"2.0\",\n error: createError(-32000),\n id: message.id || null,\n }\n\n const results: IRPCResult = {}\n\n for (const name of message.params)\n {\n if (!this.namespaces[ns].events[name])\n {\n results[name] = \"provided event invalid\"\n continue\n }\n\n const index =\n this.namespaces[ns].events[name].sockets.indexOf(socket_id)\n\n if (index === -1)\n {\n results[name] = \"not subscribed\"\n continue\n }\n\n this.namespaces[ns].events[name].sockets.splice(index, 1)\n results[name] = \"ok\"\n }\n\n return {\n jsonrpc: \"2.0\",\n result: results,\n id: message.id || null,\n }\n }\n else if (message.method === \"rpc.login\")\n {\n if (!message.params)\n return {\n jsonrpc: \"2.0\",\n error: createError(-32604),\n id: message.id || null,\n }\n }\n\n if (!this.namespaces[ns].rpc_methods[message.method])\n {\n return {\n jsonrpc: \"2.0\",\n error: createError(-32601),\n id: message.id || null,\n }\n }\n\n let response = null\n\n // reject request if method is protected and if client is not authenticated\n if (\n this.namespaces[ns].rpc_methods[message.method].protected === true &&\n this.namespaces[ns].clients.get(socket_id)[\"_authenticated\"] === false\n )\n {\n return {\n jsonrpc: \"2.0\",\n error: createError(-32605),\n id: message.id || null,\n }\n }\n\n try\n {\n response = await this.namespaces[ns].rpc_methods[message.method].fn(\n message.params,\n socket_id\n )\n }\n catch (error)\n {\n if (!message.id) return\n\n if (error instanceof Error)\n return {\n jsonrpc: \"2.0\",\n error: {\n code: -32000,\n message: error.name,\n data: error.message,\n },\n id: message.id,\n }\n\n return {\n jsonrpc: \"2.0\",\n error: error,\n id: message.id,\n }\n }\n\n // client sent a notification, so we won't need a reply\n if (!message.id) return\n\n // if login middleware returned true, set connection as authenticated\n if (message.method === \"rpc.login\" && response === true)\n {\n const s = this.namespaces[ns].clients.get(socket_id)\n s[\"_authenticated\"] = true\n this.namespaces[ns].clients.set(socket_id, s)\n }\n\n return {\n jsonrpc: \"2.0\",\n result: response,\n id: message.id,\n }\n }\n\n /**\n * Generate a new namespace store.\n * Also preregister some special namespace methods.\n * @private\n * @param {String} name - namespaces identifier\n * @return {undefined}\n */\n private _generateNamespace(name: string)\n {\n this.namespaces[name] = {\n rpc_methods: {\n __listMethods: {\n fn: () => Object.keys(this.namespaces[name].rpc_methods),\n protected: false,\n },\n },\n clients: new Map(),\n events: {},\n }\n }\n}\n\nconst RPC_ERRORS = new Map([\n [-32000, \"Event not provided\"],\n [-32600, \"Invalid Request\"],\n [-32601, \"Method not found\"],\n [-32602, \"Invalid params\"],\n [-32603, \"Internal error\"],\n [-32604, \"Params not found\"],\n [-32605, \"Method forbidden\"],\n [-32606, \"Event forbidden\"],\n [-32700, \"Parse error\"],\n])\n\n/**\n * Creates a JSON-RPC 2.0-compliant error.\n * @param {Number} code - error code\n * @param {String} details - error details\n * @return {Object}\n */\nexport function createError(code: number, details?: string)\n{\n const error: IRPCError = {\n code: code,\n message: RPC_ERRORS.get(code) || \"Internal Server Error\",\n }\n\n if (details) error[\"data\"] = details\n\n return error\n}\n","\"use strict\"\n\nimport { WebSocket } from \"./lib/client/websocket.js\"\nimport { CommonClient } from \"./lib/client.js\"\nimport {\n NodeWebSocketTypeOptions,\n IWSClientAdditionalOptions,\n ICommonWebSocketFactory,\n} from \"./lib/client/client.types.js\"\n\nexport class Client extends CommonClient\n{\n constructor(\n address = \"ws://localhost:8080\",\n {\n autoconnect = true,\n reconnect = true,\n reconnect_interval = 1000,\n max_reconnects = 5,\n ...rest_options\n }: IWSClientAdditionalOptions & NodeWebSocketTypeOptions = {},\n generate_request_id?: (\n method: string,\n params: object | Array\n ) => number\n )\n {\n super(\n WebSocket as ICommonWebSocketFactory,\n address,\n {\n autoconnect,\n reconnect,\n reconnect_interval,\n max_reconnects,\n ...rest_options,\n },\n generate_request_id\n )\n }\n}\n\nexport * from \"./lib/client.js\"\nexport * from \"./lib/client/websocket.js\"\nexport * from \"./lib/client/client.types.js\"\nexport * from \"./lib/server.js\"\nexport * from \"./lib/utils.js\""]} \ No newline at end of file diff --git a/dist/lib/client.cjs b/dist/lib/client.cjs deleted file mode 100644 index cd8abb0..0000000 --- a/dist/lib/client.cjs +++ /dev/null @@ -1,306 +0,0 @@ -/** - * "Client" wraps "ws" or a browser-implemented "WebSocket" library - * according to the environment providing JSON RPC 2.0 support on top. - * @module Client - */ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -// @ts-ignore -const eventemitter3_1 = require("eventemitter3"); -const utils_cjs_1 = require("./utils.cjs"); -class CommonClient extends eventemitter3_1.EventEmitter { - address; - rpc_id; - queue; - options; - autoconnect; - ready; - reconnect; - reconnect_timer_id; - reconnect_interval; - max_reconnects; - rest_options; - current_reconnects; - generate_request_id; - socket; - webSocketFactory; - dataPack; - /** - * Instantiate a Client class. - * @constructor - * @param {webSocketFactory} webSocketFactory - factory method for WebSocket - * @param {String} address - url to a websocket server - * @param {Object} options - ws options object with reconnect parameters - * @param {Function} generate_request_id - custom generation request Id - * @param {DataPack} dataPack - data pack contains encoder and decoder - * @return {CommonClient} - */ - constructor(webSocketFactory, address = "ws://localhost:8080", { autoconnect = true, reconnect = true, reconnect_interval = 1000, max_reconnects = 5, ...rest_options } = {}, generate_request_id, dataPack) { - super(); - this.webSocketFactory = webSocketFactory; - this.queue = {}; - this.rpc_id = 0; - this.address = address; - this.autoconnect = autoconnect; - this.ready = false; - this.reconnect = reconnect; - this.reconnect_timer_id = undefined; - this.reconnect_interval = reconnect_interval; - this.max_reconnects = max_reconnects; - this.rest_options = rest_options; - this.current_reconnects = 0; - this.generate_request_id = generate_request_id || (() => ++this.rpc_id); - if (!dataPack) - this.dataPack = new utils_cjs_1.DefaultDataPack(); - else - this.dataPack = dataPack; - if (this.autoconnect) - this._connect(this.address, { - autoconnect: this.autoconnect, - reconnect: this.reconnect, - reconnect_interval: this.reconnect_interval, - max_reconnects: this.max_reconnects, - ...this.rest_options - }); - } - /** - * Connects to a defined server if not connected already. - * @method - * @return {Undefined} - */ - connect() { - if (this.socket) - return; - this._connect(this.address, { - autoconnect: this.autoconnect, - reconnect: this.reconnect, - reconnect_interval: this.reconnect_interval, - max_reconnects: this.max_reconnects, - ...this.rest_options - }); - } - /** - * Calls a registered RPC method on server. - * @method - * @param {String} method - RPC method name - * @param {Object|Array} params - optional method parameters - * @param {Number} timeout - RPC reply timeout value - * @param {Object} ws_opts - options passed to ws - * @return {Promise} - */ - call(method, params, timeout, ws_opts) { - if (!ws_opts && "object" === typeof timeout) { - ws_opts = timeout; - timeout = null; - } - return new Promise((resolve, reject) => { - if (!this.ready) - return reject(new Error("socket not ready")); - const rpc_id = this.generate_request_id(method, params); - const message = { - jsonrpc: "2.0", - method: method, - params: params || undefined, - id: rpc_id - }; - this.socket.send(this.dataPack.encode(message), ws_opts, (error) => { - if (error) - return reject(error); - this.queue[rpc_id] = { promise: [resolve, reject] }; - if (timeout) { - this.queue[rpc_id].timeout = setTimeout(() => { - delete this.queue[rpc_id]; - reject(new Error("reply timeout")); - }, timeout); - } - }); - }); - } - /** - * Logins with the other side of the connection. - * @method - * @param {Object} params - Login credentials object - * @return {Promise} - */ - async login(params) { - const resp = await this.call("rpc.login", params); - if (!resp) - throw new Error("authentication failed"); - return resp; - } - /** - * Fetches a list of client's methods registered on server. - * @method - * @return {Array} - */ - async listMethods() { - return await this.call("__listMethods"); - } - /** - * Sends a JSON-RPC 2.0 notification to server. - * @method - * @param {String} method - RPC method name - * @param {Object} params - optional method parameters - * @return {Promise} - */ - notify(method, params) { - return new Promise((resolve, reject) => { - if (!this.ready) - return reject(new Error("socket not ready")); - const message = { - jsonrpc: "2.0", - method: method, - params - }; - this.socket.send(this.dataPack.encode(message), (error) => { - if (error) - return reject(error); - resolve(); - }); - }); - } - /** - * Subscribes for a defined event. - * @method - * @param {String|Array} event - event name - * @return {Undefined} - * @throws {Error} - */ - async subscribe(event) { - if (typeof event === "string") - event = [event]; - const result = await this.call("rpc.on", event); - if (typeof event === "string" && result[event] !== "ok") - throw new Error("Failed subscribing to an event '" + event + "' with: " + result[event]); - return result; - } - /** - * Unsubscribes from a defined event. - * @method - * @param {String|Array} event - event name - * @return {Undefined} - * @throws {Error} - */ - async unsubscribe(event) { - if (typeof event === "string") - event = [event]; - const result = await this.call("rpc.off", event); - if (typeof event === "string" && result[event] !== "ok") - throw new Error("Failed unsubscribing from an event with: " + result); - return result; - } - /** - * Closes a WebSocket connection gracefully. - * @method - * @param {Number} code - socket close code - * @param {String} data - optional data to be sent before closing - * @return {Undefined} - */ - close(code, data) { - this.socket.close(code || 1000, data); - } - /** - * Enable / disable automatic reconnection. - * @method - * @param {Boolean} reconnect - enable / disable reconnection - * @return {Undefined} - */ - setAutoReconnect(reconnect) { - this.reconnect = reconnect; - } - /** - * Set the interval between reconnection attempts. - * @method - * @param {Number} interval - reconnection interval in milliseconds - * @return {Undefined} - */ - setReconnectInterval(interval) { - this.reconnect_interval = interval; - } - /** - * Set the maximum number of reconnection attempts. - * @method - * @param {Number} max_reconnects - maximum reconnection attempts - * @return {Undefined} - */ - setMaxReconnects(max_reconnects) { - this.max_reconnects = max_reconnects; - } - /** - * Connection/Message handler. - * @method - * @private - * @param {String} address - WebSocket API address - * @param {Object} options - ws options object - * @return {Undefined} - */ - _connect(address, options) { - clearTimeout(this.reconnect_timer_id); - this.socket = this.webSocketFactory(address, options); - this.socket.addEventListener("open", () => { - this.ready = true; - this.emit("open"); - this.current_reconnects = 0; - }); - this.socket.addEventListener("message", ({ data: message }) => { - if (message instanceof ArrayBuffer) - message = Buffer.from(message).toString(); - try { - message = this.dataPack.decode(message); - } - catch (error) { - return; - } - // check if any listeners are attached and forward event - if (message.notification && this.listeners(message.notification).length) { - if (!Object.keys(message.params).length) - return this.emit(message.notification); - const args = [message.notification]; - if (message.params.constructor === Object) - args.push(message.params); - else - // using for-loop instead of unshift/spread because performance is better - for (let i = 0; i < message.params.length; i++) - args.push(message.params[i]); - // run as microtask so that pending queue messages are resolved first - // eslint-disable-next-line prefer-spread - return Promise.resolve().then(() => { this.emit.apply(this, args); }); - } - if (!this.queue[message.id]) { - // general JSON RPC 2.0 events - if (message.method) { - // run as microtask so that pending queue messages are resolved first - return Promise.resolve().then(() => { - this.emit(message.method, message?.params); - }); - } - return; - } - // reject early since server's response is invalid - if ("error" in message === "result" in message) - this.queue[message.id].promise[1](new Error("Server response malformed. Response must include either \"result\"" + - " or \"error\", but not both.")); - if (this.queue[message.id].timeout) - clearTimeout(this.queue[message.id].timeout); - if (message.error) - this.queue[message.id].promise[1](message.error); - else - this.queue[message.id].promise[0](message.result); - delete this.queue[message.id]; - }); - this.socket.addEventListener("error", (error) => this.emit("error", error)); - this.socket.addEventListener("close", ({ code, reason }) => { - if (this.ready) // Delay close event until internal state is updated - setTimeout(() => this.emit("close", code, reason), 0); - this.ready = false; - this.socket = undefined; - if (code === 1000) - return; - this.current_reconnects++; - if (this.reconnect && ((this.max_reconnects > this.current_reconnects) || - this.max_reconnects === 0)) - this.reconnect_timer_id = setTimeout(() => this._connect(address, options), this.reconnect_interval); - }); - } -} -exports.default = CommonClient; diff --git a/dist/lib/client.d.cts b/dist/lib/client.d.cts deleted file mode 100644 index 2c97467..0000000 --- a/dist/lib/client.d.cts +++ /dev/null @@ -1,148 +0,0 @@ -/** - * "Client" wraps "ws" or a browser-implemented "WebSocket" library - * according to the environment providing JSON RPC 2.0 support on top. - * @module Client - */ -import { EventEmitter } from "eventemitter3"; -import { NodeWebSocketType, ICommonWebSocketFactory } from "./client/client.types.cjs"; -import { DataPack } from "./utils.cjs"; -interface IQueueElement { - promise: [ - Parameters[0]>[0], - Parameters[0]>[1] - ]; - timeout?: ReturnType; -} -export interface IQueue { - [x: number]: IQueueElement; -} -export interface IWSRequestParams { - [x: string]: any; - [x: number]: any; -} -export default class CommonClient extends EventEmitter { - private address; - private rpc_id; - private queue; - private options; - private autoconnect; - private ready; - private reconnect; - private reconnect_timer_id; - private reconnect_interval; - private max_reconnects; - private rest_options; - private current_reconnects; - private generate_request_id; - private socket; - private webSocketFactory; - private dataPack; - /** - * Instantiate a Client class. - * @constructor - * @param {webSocketFactory} webSocketFactory - factory method for WebSocket - * @param {String} address - url to a websocket server - * @param {Object} options - ws options object with reconnect parameters - * @param {Function} generate_request_id - custom generation request Id - * @param {DataPack} dataPack - data pack contains encoder and decoder - * @return {CommonClient} - */ - constructor(webSocketFactory: ICommonWebSocketFactory, address?: string, { autoconnect, reconnect, reconnect_interval, max_reconnects, ...rest_options }?: { - autoconnect?: boolean; - reconnect?: boolean; - reconnect_interval?: number; - max_reconnects?: number; - }, generate_request_id?: (method: string, params: object | Array) => number, dataPack?: DataPack); - /** - * Connects to a defined server if not connected already. - * @method - * @return {Undefined} - */ - connect(): void; - /** - * Calls a registered RPC method on server. - * @method - * @param {String} method - RPC method name - * @param {Object|Array} params - optional method parameters - * @param {Number} timeout - RPC reply timeout value - * @param {Object} ws_opts - options passed to ws - * @return {Promise} - */ - call(method: string, params?: IWSRequestParams, timeout?: number, ws_opts?: Parameters[1]): Promise; - /** - * Logins with the other side of the connection. - * @method - * @param {Object} params - Login credentials object - * @return {Promise} - */ - login(params: IWSRequestParams): Promise; - /** - * Fetches a list of client's methods registered on server. - * @method - * @return {Array} - */ - listMethods(): Promise; - /** - * Sends a JSON-RPC 2.0 notification to server. - * @method - * @param {String} method - RPC method name - * @param {Object} params - optional method parameters - * @return {Promise} - */ - notify(method: string, params?: IWSRequestParams): Promise; - /** - * Subscribes for a defined event. - * @method - * @param {String|Array} event - event name - * @return {Undefined} - * @throws {Error} - */ - subscribe(event: string | Array): Promise; - /** - * Unsubscribes from a defined event. - * @method - * @param {String|Array} event - event name - * @return {Undefined} - * @throws {Error} - */ - unsubscribe(event: string | Array): Promise; - /** - * Closes a WebSocket connection gracefully. - * @method - * @param {Number} code - socket close code - * @param {String} data - optional data to be sent before closing - * @return {Undefined} - */ - close(code?: number, data?: string): void; - /** - * Enable / disable automatic reconnection. - * @method - * @param {Boolean} reconnect - enable / disable reconnection - * @return {Undefined} - */ - setAutoReconnect(reconnect: boolean): void; - /** - * Set the interval between reconnection attempts. - * @method - * @param {Number} interval - reconnection interval in milliseconds - * @return {Undefined} - */ - setReconnectInterval(interval: number): void; - /** - * Set the maximum number of reconnection attempts. - * @method - * @param {Number} max_reconnects - maximum reconnection attempts - * @return {Undefined} - */ - setMaxReconnects(max_reconnects: number): void; - /** - * Connection/Message handler. - * @method - * @private - * @param {String} address - WebSocket API address - * @param {Object} options - ws options object - * @return {Undefined} - */ - private _connect; -} -export {}; diff --git a/dist/lib/client/client.types.cjs b/dist/lib/client/client.types.cjs deleted file mode 100644 index c8ad2e5..0000000 --- a/dist/lib/client/client.types.cjs +++ /dev/null @@ -1,2 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); diff --git a/dist/lib/client/client.types.d.cts b/dist/lib/client/client.types.d.cts deleted file mode 100644 index ccc0479..0000000 --- a/dist/lib/client/client.types.d.cts +++ /dev/null @@ -1,18 +0,0 @@ -import NodeWebSocket from "ws"; -export type BrowserWebSocketType = InstanceType; -export type NodeWebSocketType = InstanceType; -export type NodeWebSocketTypeOptions = NodeWebSocket.ClientOptions; -export interface IWSClientAdditionalOptions { - autoconnect?: boolean; - reconnect?: boolean; - reconnect_interval?: number; - max_reconnects?: number; -} -export interface ICommonWebSocketFactory { - (address: string, options: IWSClientAdditionalOptions): ICommonWebSocket; -} -export interface ICommonWebSocket { - send: (data: Parameters[0], optionsOrCallback: ((error?: Error) => void) | Parameters[1], callback?: (error?: Error) => void) => void; - close: (code?: number, reason?: string) => void; - addEventListener(type: K, listener: (ev: WebSocketEventMap[K]) => any, options?: boolean | AddEventListenerOptions): void; -} diff --git a/dist/lib/client/websocket.browser.cjs b/dist/lib/client/websocket.browser.cjs deleted file mode 100644 index a8a58f4..0000000 --- a/dist/lib/client/websocket.browser.cjs +++ /dev/null @@ -1,70 +0,0 @@ -/** - * WebSocket implements a browser-side WebSocket specification. - * @module Client - */ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -const eventemitter3_1 = require("eventemitter3"); -class WebSocketBrowserImpl extends eventemitter3_1.EventEmitter { - socket; - /** Instantiate a WebSocket class - * @constructor - * @param {String} address - url to a websocket server - * @param {(Object)} options - websocket options - * @param {(String|Array)} protocols - a list of protocols - * @return {WebSocketBrowserImpl} - returns a WebSocket instance - */ - constructor(address, options, protocols) { - super(); - this.socket = new window.WebSocket(address, protocols); - this.socket.onopen = () => this.emit("open"); - this.socket.onmessage = (event) => this.emit("message", event.data); - this.socket.onerror = (error) => this.emit("error", error); - this.socket.onclose = (event) => { - this.emit("close", event.code, event.reason); - }; - } - /** - * Sends data through a websocket connection - * @method - * @param {(String|Object)} data - data to be sent via websocket - * @param {Object} optionsOrCallback - ws options - * @param {Function} callback - a callback called once the data is sent - * @return {Undefined} - */ - send(data, optionsOrCallback, callback) { - const cb = callback || optionsOrCallback; - try { - this.socket.send(data); - cb(); - } - catch (error) { - cb(error); - } - } - /** - * Closes an underlying socket - * @method - * @param {Number} code - status code explaining why the connection is being closed - * @param {String} reason - a description why the connection is closing - * @return {Undefined} - * @throws {Error} - */ - close(code, reason) { - this.socket.close(code, reason); - } - addEventListener(type, listener, options) { - this.socket.addEventListener(type, listener, options); - } -} -/** - * factory method for common WebSocket instance - * @method - * @param {String} address - url to a websocket server - * @param {(Object)} options - websocket options - * @return {Undefined} - */ -function default_1(address, options) { - return new WebSocketBrowserImpl(address, options); -} -exports.default = default_1; diff --git a/dist/lib/client/websocket.browser.d.cts b/dist/lib/client/websocket.browser.d.cts deleted file mode 100644 index 98da72c..0000000 --- a/dist/lib/client/websocket.browser.d.cts +++ /dev/null @@ -1,45 +0,0 @@ -/** - * WebSocket implements a browser-side WebSocket specification. - * @module Client - */ -import { EventEmitter } from "eventemitter3"; -import { BrowserWebSocketType, NodeWebSocketType, IWSClientAdditionalOptions } from "./client.types.cjs"; -declare class WebSocketBrowserImpl extends EventEmitter { - socket: BrowserWebSocketType; - /** Instantiate a WebSocket class - * @constructor - * @param {String} address - url to a websocket server - * @param {(Object)} options - websocket options - * @param {(String|Array)} protocols - a list of protocols - * @return {WebSocketBrowserImpl} - returns a WebSocket instance - */ - constructor(address: string, options: {}, protocols?: string | string[]); - /** - * Sends data through a websocket connection - * @method - * @param {(String|Object)} data - data to be sent via websocket - * @param {Object} optionsOrCallback - ws options - * @param {Function} callback - a callback called once the data is sent - * @return {Undefined} - */ - send(data: Parameters[0], optionsOrCallback: (error?: Error) => void | Parameters[1], callback?: () => void): void; - /** - * Closes an underlying socket - * @method - * @param {Number} code - status code explaining why the connection is being closed - * @param {String} reason - a description why the connection is closing - * @return {Undefined} - * @throws {Error} - */ - close(code?: number, reason?: string): void; - addEventListener(type: K, listener: (ev: WebSocketEventMap[K]) => any, options?: boolean | AddEventListenerOptions): void; -} -/** - * factory method for common WebSocket instance - * @method - * @param {String} address - url to a websocket server - * @param {(Object)} options - websocket options - * @return {Undefined} - */ -export default function (address: string, options: IWSClientAdditionalOptions): WebSocketBrowserImpl; -export {}; diff --git a/dist/lib/client/websocket.cjs b/dist/lib/client/websocket.cjs deleted file mode 100644 index 6e6cd50..0000000 --- a/dist/lib/client/websocket.cjs +++ /dev/null @@ -1,18 +0,0 @@ -/* A wrapper for the "qaap/uws-bindings" library. */ -"use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -const ws_1 = __importDefault(require("ws")); -/** - * factory method for common WebSocket instance - * @method - * @param {String} address - url to a websocket server - * @param {(Object)} options - websocket options - * @return {Undefined} - */ -function default_1(address, options) { - return new ws_1.default(address, options); -} -exports.default = default_1; diff --git a/dist/lib/client/websocket.d.cts b/dist/lib/client/websocket.d.cts deleted file mode 100644 index 85016b1..0000000 --- a/dist/lib/client/websocket.d.cts +++ /dev/null @@ -1,10 +0,0 @@ -import WebSocket from "ws"; -import { IWSClientAdditionalOptions } from "./client.types.cjs"; -/** - * factory method for common WebSocket instance - * @method - * @param {String} address - url to a websocket server - * @param {(Object)} options - websocket options - * @return {Undefined} - */ -export default function (address: string, options: IWSClientAdditionalOptions & WebSocket.ClientOptions): WebSocket; diff --git a/dist/lib/server.cjs b/dist/lib/server.cjs deleted file mode 100644 index 97d8c3d..0000000 --- a/dist/lib/server.cjs +++ /dev/null @@ -1,597 +0,0 @@ -/** - * "Server" wraps the "ws" library providing JSON RPC 2.0 support on top. - * @module Server - */ -"use strict"; -var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - var desc = Object.getOwnPropertyDescriptor(m, k); - if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { - desc = { enumerable: true, get: function() { return m[k]; } }; - } - Object.defineProperty(o, k2, desc); -}) : (function(o, m, k, k2) { - if (k2 === undefined) k2 = k; - o[k2] = m[k]; -})); -var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { - Object.defineProperty(o, "default", { enumerable: true, value: v }); -}) : function(o, v) { - o["default"] = v; -}); -var __importStar = (this && this.__importStar) || function (mod) { - if (mod && mod.__esModule) return mod; - var result = {}; - if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); - __setModuleDefault(result, mod); - return result; -}; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -// @ts-ignore -const eventemitter3_1 = require("eventemitter3"); -const ws_1 = require("ws"); -const uuid_1 = require("uuid"); -const url_1 = __importDefault(require("url")); -const utils = __importStar(require("./utils.cjs")); -class Server extends eventemitter3_1.EventEmitter { - namespaces; - dataPack; - wss; - /** - * Instantiate a Server class. - * @constructor - * @param {Object} options - ws constructor's parameters with rpc - * @param {DataPack} dataPack - data pack contains encoder and decoder - * @return {Server} - returns a new Server instance - */ - constructor(options, dataPack) { - super(); - /** - * Stores all connected sockets with a universally unique identifier - * in the appropriate namespace. - * Stores all rpc methods to specific namespaces. "/" by default. - * Stores all events as keys and subscribed users in array as value - * @private - * @name namespaces - * @param {Object} namespaces.rpc_methods - * @param {Map} namespaces.clients - * @param {Object} namespaces.events - */ - this.namespaces = {}; - if (!dataPack) - this.dataPack = new utils.DefaultDataPack(); - else - this.dataPack = dataPack; - this.wss = new ws_1.Server(options); - this.wss.on("listening", () => this.emit("listening")); - this.wss.on("connection", (socket, request) => { - const u = url_1.default.parse(request.url, true); - const ns = u.pathname; - if (u.query.socket_id) - socket._id = u.query.socket_id; - else - socket._id = (0, uuid_1.v1)(); - // unauthenticated by default - socket["_authenticated"] = false; - // propagate socket errors - socket.on("error", (error) => this.emit("socket-error", socket, error)); - // cleanup after the socket gets disconnected - socket.on("close", () => { - this.namespaces[ns].clients.delete(socket._id); - for (const event of Object.keys(this.namespaces[ns].events)) { - const index = this.namespaces[ns].events[event].sockets.indexOf(socket._id); - if (index >= 0) - this.namespaces[ns].events[event].sockets.splice(index, 1); - } - this.emit("disconnection", socket); - }); - if (!this.namespaces[ns]) - this._generateNamespace(ns); - // store socket and method - this.namespaces[ns].clients.set(socket._id, socket); - this.emit("connection", socket, request); - return this._handleRPC(socket, ns); - }); - this.wss.on("error", (error) => this.emit("error", error)); - } - /** - * Registers an RPC method. - * @method - * @param {String} name - method name - * @param {Function} fn - a callee function - * @param {String} ns - namespace identifier - * @throws {TypeError} - * @return {Object} - returns an IMethod object - */ - register(name, fn, ns = "/") { - if (!this.namespaces[ns]) - this._generateNamespace(ns); - this.namespaces[ns].rpc_methods[name] = { - fn: fn, - protected: false - }; - return { - protected: () => this._makeProtectedMethod(name, ns), - public: () => this._makePublicMethod(name, ns) - }; - } - /** - * Sets an auth method. - * @method - * @param {Function} fn - an arbitrary auth method - * @param {String} ns - namespace identifier - * @throws {TypeError} - * @return {Undefined} - */ - setAuth(fn, ns = "/") { - this.register("rpc.login", fn, ns); - } - /** - * Marks an RPC method as protected. - * @method - * @param {String} name - method name - * @param {String} ns - namespace identifier - * @return {Undefined} - */ - _makeProtectedMethod(name, ns = "/") { - this.namespaces[ns].rpc_methods[name].protected = true; - } - /** - * Marks an RPC method as public. - * @method - * @param {String} name - method name - * @param {String} ns - namespace identifier - * @return {Undefined} - */ - _makePublicMethod(name, ns = "/") { - this.namespaces[ns].rpc_methods[name].protected = false; - } - /** - * Marks an event as protected. - * @method - * @param {String} name - event name - * @param {String} ns - namespace identifier - * @return {Undefined} - */ - _makeProtectedEvent(name, ns = "/") { - this.namespaces[ns].events[name].protected = true; - } - /** - * Marks an event as public. - * @method - * @param {String} name - event name - * @param {String} ns - namespace identifier - * @return {Undefined} - */ - _makePublicEvent(name, ns = "/") { - this.namespaces[ns].events[name].protected = false; - } - /** - * Removes a namespace and closes all connections - * @method - * @param {String} ns - namespace identifier - * @throws {TypeError} - * @return {Undefined} - */ - closeNamespace(ns) { - const namespace = this.namespaces[ns]; - if (namespace) { - delete namespace.rpc_methods; - delete namespace.events; - for (const socket of namespace.clients.values()) - socket.close(); - delete this.namespaces[ns]; - } - } - /** - * Creates a new event that can be emitted to clients. - * @method - * @param {String} name - event name - * @param {String} ns - namespace identifier - * @throws {TypeError} - * @return {Object} - returns an IEvent object - */ - event(name, ns = "/") { - if (!this.namespaces[ns]) - this._generateNamespace(ns); - else { - const index = this.namespaces[ns].events[name]; - if (index !== undefined) - throw new Error(`Already registered event ${ns}${name}`); - } - this.namespaces[ns].events[name] = { - sockets: [], - protected: false - }; - // forward emitted event to subscribers - this.on(name, (...params) => { - // flatten an object if no spreading is wanted - if (params.length === 1 && params[0] instanceof Object) - params = params[0]; - for (const socket_id of this.namespaces[ns].events[name].sockets) { - const socket = this.namespaces[ns].clients.get(socket_id); - if (!socket) - continue; - socket.send(this.dataPack.encode({ - notification: name, - params - })); - } - }); - return { - protected: () => this._makeProtectedEvent(name, ns), - public: () => this._makePublicEvent(name, ns) - }; - } - /** - * Returns a requested namespace object - * @method - * @param {String} name - namespace identifier - * @throws {TypeError} - * @return {Object} - namespace object - */ - of(name) { - if (!this.namespaces[name]) - this._generateNamespace(name); - const self = this; - return { - // self.register convenience method - register(fn_name, fn) { - if (arguments.length !== 2) - throw new Error("must provide exactly two arguments"); - if (typeof fn_name !== "string") - throw new Error("name must be a string"); - if (typeof fn !== "function") - throw new Error("handler must be a function"); - return self.register(fn_name, fn, name); - }, - // self.event convenience method - event(ev_name) { - if (arguments.length !== 1) - throw new Error("must provide exactly one argument"); - if (typeof ev_name !== "string") - throw new Error("name must be a string"); - return self.event(ev_name, name); - }, - // self.eventList convenience method - get eventList() { - return Object.keys(self.namespaces[name].events); - }, - /** - * Emits a specified event to this namespace. - * @inner - * @method - * @param {String} event - event name - * @param {Array} params - event parameters - * @return {Undefined} - */ - emit(event, ...params) { - const socket_ids = [...self.namespaces[name].clients.keys()]; - for (let i = 0, id; id = socket_ids[i]; ++i) { - self.namespaces[name].clients.get(id).send(self.dataPack.encode({ - notification: event, - params: params || [] - })); - } - }, - /** - * Returns a name of this namespace. - * @inner - * @method - * @kind constant - * @return {String} - */ - get name() { - return name; - }, - /** - * Returns a hash of websocket objects connected to this namespace. - * @inner - * @method - * @return {Object} - */ - connected() { - const socket_ids = [...self.namespaces[name].clients.keys()]; - return socket_ids.reduce((acc, curr) => ({ - ...acc, - [curr]: self.namespaces[name].clients.get(curr) - }), {}); - }, - /** - * Returns a list of client unique identifiers connected to this namespace. - * @inner - * @method - * @return {Array} - */ - clients() { - return self.namespaces[name]; - } - }; - } - /** - * Lists all created events in a given namespace. Defaults to "/". - * @method - * @param {String} ns - namespaces identifier - * @readonly - * @return {Array} - returns a list of created events - */ - eventList(ns = "/") { - if (!this.namespaces[ns]) - return []; - return Object.keys(this.namespaces[ns].events); - } - /** - * Creates a JSON-RPC 2.0 compliant error - * @method - * @param {Number} code - indicates the error type that occurred - * @param {String} message - provides a short description of the error - * @param {String|Object} data - details containing additional information about the error - * @return {Object} - */ - createError(code, message, data) { - return { - code: code, - message: message, - data: data || null - }; - } - /** - * Closes the server and terminates all clients. - * @method - * @return {Promise} - */ - close() { - return new Promise((resolve, reject) => { - try { - this.wss.close(); - this.emit("close"); - resolve(); - } - catch (error) { - reject(error); - } - }); - } - /** - * Handles all WebSocket JSON RPC 2.0 requests. - * @private - * @param {Object} socket - ws socket instance - * @param {String} ns - namespaces identifier - * @return {Undefined} - */ - _handleRPC(socket, ns = "/") { - socket.on("message", async (data) => { - const msg_options = {}; - if (data instanceof ArrayBuffer) { - msg_options.binary = true; - data = Buffer.from(data).toString(); - } - if (socket.readyState !== 1) - return; // TODO: should have debug logs here - let parsedData; - try { - parsedData = this.dataPack.decode(data); - } - catch (error) { - return socket.send(this.dataPack.encode({ - jsonrpc: "2.0", - error: utils.createError(-32700, error.toString()), - id: null - }), msg_options); - } - if (Array.isArray(parsedData)) { - if (!parsedData.length) - return socket.send(this.dataPack.encode({ - jsonrpc: "2.0", - error: utils.createError(-32600, "Invalid array"), - id: null - }), msg_options); - const responses = []; - for (const message of parsedData) { - const response = await this._runMethod(message, socket._id, ns); - if (!response) - continue; - responses.push(response); - } - if (!responses.length) - return; - return socket.send(this.dataPack.encode(responses), msg_options); - } - const response = await this._runMethod(parsedData, socket._id, ns); - if (!response) - return; - return socket.send(this.dataPack.encode(response), msg_options); - }); - } - /** - * Runs a defined RPC method. - * @private - * @param {Object} message - a message received - * @param {Object} socket_id - user's socket id - * @param {String} ns - namespaces identifier - * @return {Object|undefined} - */ - async _runMethod(message, socket_id, ns = "/") { - if (typeof message !== "object" || message === null) - return { - jsonrpc: "2.0", - error: utils.createError(-32600), - id: null - }; - if (message.jsonrpc !== "2.0") - return { - jsonrpc: "2.0", - error: utils.createError(-32600, "Invalid JSON RPC version"), - id: message.id || null - }; - if (!message.method) - return { - jsonrpc: "2.0", - error: utils.createError(-32602, "Method not specified"), - id: message.id || null - }; - if (typeof message.method !== "string") - return { - jsonrpc: "2.0", - error: utils.createError(-32600, "Invalid method name"), - id: message.id || null - }; - if (message.params && typeof message.params === "string") - return { - jsonrpc: "2.0", - error: utils.createError(-32600), - id: message.id || null - }; - if (message.method === "rpc.on") { - if (!message.params) - return { - jsonrpc: "2.0", - error: utils.createError(-32000), - id: message.id || null - }; - const results = {}; - const event_names = Object.keys(this.namespaces[ns].events); - for (const name of message.params) { - const index = event_names.indexOf(name); - const namespace = this.namespaces[ns]; - if (index === -1) { - results[name] = "provided event invalid"; - continue; - } - // reject request if event is protected and if client is not authenticated - if (namespace.events[event_names[index]].protected === true && - namespace.clients.get(socket_id)["_authenticated"] === false) { - return { - jsonrpc: "2.0", - error: utils.createError(-32606), - id: message.id || null - }; - } - const socket_index = namespace.events[event_names[index]].sockets.indexOf(socket_id); - if (socket_index >= 0) { - results[name] = "socket has already been subscribed to event"; - continue; - } - namespace.events[event_names[index]].sockets.push(socket_id); - results[name] = "ok"; - } - return { - jsonrpc: "2.0", - result: results, - id: message.id || null - }; - } - else if (message.method === "rpc.off") { - if (!message.params) - return { - jsonrpc: "2.0", - error: utils.createError(-32000), - id: message.id || null - }; - const results = {}; - for (const name of message.params) { - if (!this.namespaces[ns].events[name]) { - results[name] = "provided event invalid"; - continue; - } - const index = this.namespaces[ns].events[name].sockets.indexOf(socket_id); - if (index === -1) { - results[name] = "not subscribed"; - continue; - } - this.namespaces[ns].events[name].sockets.splice(index, 1); - results[name] = "ok"; - } - return { - jsonrpc: "2.0", - result: results, - id: message.id || null - }; - } - else if (message.method === "rpc.login") { - if (!message.params) - return { - jsonrpc: "2.0", - error: utils.createError(-32604), - id: message.id || null - }; - } - if (!this.namespaces[ns].rpc_methods[message.method]) { - return { - jsonrpc: "2.0", - error: utils.createError(-32601), - id: message.id || null - }; - } - let response = null; - // reject request if method is protected and if client is not authenticated - if (this.namespaces[ns].rpc_methods[message.method].protected === true && - this.namespaces[ns].clients.get(socket_id)["_authenticated"] === false) { - return { - jsonrpc: "2.0", - error: utils.createError(-32605), - id: message.id || null - }; - } - try { - response = await this.namespaces[ns].rpc_methods[message.method] - .fn(message.params, socket_id); - } - catch (error) { - if (!message.id) - return; - if (error instanceof Error) - return { - jsonrpc: "2.0", - error: { - code: -32000, - message: error.name, - data: error.message - }, - id: message.id - }; - return { - jsonrpc: "2.0", - error: error, - id: message.id - }; - } - // client sent a notification, so we won't need a reply - if (!message.id) - return; - // if login middleware returned true, set connection as authenticated - if (message.method === "rpc.login" && response === true) { - const s = this.namespaces[ns].clients.get(socket_id); - s["_authenticated"] = true; - this.namespaces[ns].clients.set(socket_id, s); - } - return { - jsonrpc: "2.0", - result: response, - id: message.id - }; - } - /** - * Generate a new namespace store. - * Also preregister some special namespace methods. - * @private - * @param {String} name - namespaces identifier - * @return {undefined} - */ - _generateNamespace(name) { - this.namespaces[name] = { - rpc_methods: { - "__listMethods": { - fn: () => Object.keys(this.namespaces[name].rpc_methods), - protected: false - } - }, - clients: new Map(), - events: {} - }; - } -} -exports.default = Server; diff --git a/dist/lib/server.d.cts b/dist/lib/server.d.cts deleted file mode 100644 index 8b8bf15..0000000 --- a/dist/lib/server.d.cts +++ /dev/null @@ -1,215 +0,0 @@ -/** - * "Server" wraps the "ws" library providing JSON RPC 2.0 support on top. - * @module Server - */ -import { EventEmitter } from "eventemitter3"; -import NodeWebSocket, { Server as WebSocketServer } from "ws"; -import * as utils from "./utils.cjs"; -interface INamespaceEvent { - [x: string]: { - sockets: Array; - protected: boolean; - }; -} -interface IMethod { - public: () => void; - protected: () => void; -} -interface IEvent { - public: () => void; - protected: () => void; -} -interface IRPCMethodParams { - [x: string]: any; -} -interface IRPCMethod { - [x: string]: { - fn: (params: IRPCMethodParams, socket_id: string) => any; - protected: boolean; - }; -} -interface IClientWebSocket extends NodeWebSocket { - _id: string; - _authenticated: boolean; -} -export default class Server extends EventEmitter { - private namespaces; - private dataPack; - wss: InstanceType; - /** - * Instantiate a Server class. - * @constructor - * @param {Object} options - ws constructor's parameters with rpc - * @param {DataPack} dataPack - data pack contains encoder and decoder - * @return {Server} - returns a new Server instance - */ - constructor(options: NodeWebSocket.ServerOptions, dataPack?: utils.DataPack); - /** - * Registers an RPC method. - * @method - * @param {String} name - method name - * @param {Function} fn - a callee function - * @param {String} ns - namespace identifier - * @throws {TypeError} - * @return {Object} - returns an IMethod object - */ - register(name: string, fn: (params: IRPCMethodParams, socket_id: string) => void, ns?: string): IMethod; - /** - * Sets an auth method. - * @method - * @param {Function} fn - an arbitrary auth method - * @param {String} ns - namespace identifier - * @throws {TypeError} - * @return {Undefined} - */ - setAuth(fn: (params: IRPCMethodParams, socket_id: string) => Promise, ns?: string): void; - /** - * Marks an RPC method as protected. - * @method - * @param {String} name - method name - * @param {String} ns - namespace identifier - * @return {Undefined} - */ - private _makeProtectedMethod; - /** - * Marks an RPC method as public. - * @method - * @param {String} name - method name - * @param {String} ns - namespace identifier - * @return {Undefined} - */ - private _makePublicMethod; - /** - * Marks an event as protected. - * @method - * @param {String} name - event name - * @param {String} ns - namespace identifier - * @return {Undefined} - */ - private _makeProtectedEvent; - /** - * Marks an event as public. - * @method - * @param {String} name - event name - * @param {String} ns - namespace identifier - * @return {Undefined} - */ - private _makePublicEvent; - /** - * Removes a namespace and closes all connections - * @method - * @param {String} ns - namespace identifier - * @throws {TypeError} - * @return {Undefined} - */ - closeNamespace(ns: string): void; - /** - * Creates a new event that can be emitted to clients. - * @method - * @param {String} name - event name - * @param {String} ns - namespace identifier - * @throws {TypeError} - * @return {Object} - returns an IEvent object - */ - event(name: string, ns?: string): IEvent; - /** - * Returns a requested namespace object - * @method - * @param {String} name - namespace identifier - * @throws {TypeError} - * @return {Object} - namespace object - */ - of(name: string): { - register(fn_name: string, fn: (params: IRPCMethodParams) => void): IMethod; - event(ev_name: string): IEvent; - readonly eventList: string[]; - /** - * Emits a specified event to this namespace. - * @inner - * @method - * @param {String} event - event name - * @param {Array} params - event parameters - * @return {Undefined} - */ - emit(event: string, ...params: Array): void; - /** - * Returns a name of this namespace. - * @inner - * @method - * @kind constant - * @return {String} - */ - readonly name: string; - /** - * Returns a hash of websocket objects connected to this namespace. - * @inner - * @method - * @return {Object} - */ - connected(): {}; - /** - * Returns a list of client unique identifiers connected to this namespace. - * @inner - * @method - * @return {Array} - */ - clients(): { - rpc_methods: IRPCMethod; - clients: Map; - events: INamespaceEvent; - }; - }; - /** - * Lists all created events in a given namespace. Defaults to "/". - * @method - * @param {String} ns - namespaces identifier - * @readonly - * @return {Array} - returns a list of created events - */ - eventList(ns?: string): string[]; - /** - * Creates a JSON-RPC 2.0 compliant error - * @method - * @param {Number} code - indicates the error type that occurred - * @param {String} message - provides a short description of the error - * @param {String|Object} data - details containing additional information about the error - * @return {Object} - */ - createError(code: number, message: string, data: string | object): { - code: number; - message: string; - data: string | object; - }; - /** - * Closes the server and terminates all clients. - * @method - * @return {Promise} - */ - close(): Promise; - /** - * Handles all WebSocket JSON RPC 2.0 requests. - * @private - * @param {Object} socket - ws socket instance - * @param {String} ns - namespaces identifier - * @return {Undefined} - */ - private _handleRPC; - /** - * Runs a defined RPC method. - * @private - * @param {Object} message - a message received - * @param {Object} socket_id - user's socket id - * @param {String} ns - namespaces identifier - * @return {Object|undefined} - */ - private _runMethod; - /** - * Generate a new namespace store. - * Also preregister some special namespace methods. - * @private - * @param {String} name - namespaces identifier - * @return {undefined} - */ - private _generateNamespace; -} -export {}; diff --git a/dist/lib/utils.cjs b/dist/lib/utils.cjs deleted file mode 100644 index 8d6ee2d..0000000 --- a/dist/lib/utils.cjs +++ /dev/null @@ -1,39 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.createError = exports.DefaultDataPack = void 0; -const errors = new Map([ - [-32000, "Event not provided"], - [-32600, "Invalid Request"], - [-32601, "Method not found"], - [-32602, "Invalid params"], - [-32603, "Internal error"], - [-32604, "Params not found"], - [-32605, "Method forbidden"], - [-32606, "Event forbidden"], - [-32700, "Parse error"] -]); -class DefaultDataPack { - encode(value) { - return JSON.stringify(value); - } - decode(value) { - return JSON.parse(value); - } -} -exports.DefaultDataPack = DefaultDataPack; -/** - * Creates a JSON-RPC 2.0-compliant error. - * @param {Number} code - error code - * @param {String} details - error details - * @return {Object} - */ -function createError(code, details) { - const error = { - code: code, - message: errors.get(code) || "Internal Server Error" - }; - if (details) - error["data"] = details; - return error; -} -exports.createError = createError; diff --git a/dist/lib/utils.d.cts b/dist/lib/utils.d.cts deleted file mode 100644 index 60e964c..0000000 --- a/dist/lib/utils.d.cts +++ /dev/null @@ -1,21 +0,0 @@ -interface IRPCError { - code: number; - message: string; - data?: string; -} -export interface DataPack { - encode(value: T): R; - decode(value: R): T; -} -export declare class DefaultDataPack implements DataPack { - encode(value: Object): string; - decode(value: string): Object; -} -/** - * Creates a JSON-RPC 2.0-compliant error. - * @param {Number} code - error code - * @param {String} details - error details - * @return {Object} - */ -declare function createError(code: number, details?: string): IRPCError; -export { createError }; diff --git a/package-lock.json b/package-lock.json index 68f66e1..80c42bb 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,29 +9,29 @@ "version": "8.0.1", "license": "LGPL-3.0-only", "dependencies": { + "@swc/helpers": "^0.5.11", + "@types/uuid": "^8.3.4", + "@types/ws": "^8.2.2", + "buffer": "^6.0.3", "eventemitter3": "^4.0.7", "uuid": "^8.3.2", "ws": "^8.5.0" }, "devDependencies": { - "@babel/core": "^7.24.5", - "@babel/plugin-transform-runtime": "^7.17.0", - "@babel/preset-env": "^7.16.11", - "@types/uuid": "^8.3.4", - "@types/ws": "^8.2.2", + "@microsoft/api-extractor": "^7.47.0", "@typescript-eslint/eslint-plugin": "^5.11.0", "@typescript-eslint/parser": "^5.11.0", "async": "^3.2.3", - "babel-eslint": "^10.1.0", "chai": "^4.3.6", "coveralls": "^3.1.1", - "esbuild": "^0.20.2", - "esbuild-plugin-babel": "^0.2.3", + "esbuild-plugin-polyfill-node": "^0.3.0", "eslint": "^8.8.0", "istanbul": "^0.4.5", "mocha": "^10.0.0", "mocha-lcov-reporter": "^1.3.0", - "typescript": "^4.5.5" + "tsup": "^8.1.0", + "typescript": "^4.5.5", + "url": "^0.11.3" }, "funding": { "type": "paypal", @@ -51,2034 +51,1262 @@ "node": ">=0.10.0" } }, - "node_modules/@ampproject/remapping": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", - "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", + "node_modules/@esbuild/aix-ppc64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz", + "integrity": "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==", + "cpu": [ + "ppc64" + ], "dev": true, - "dependencies": { - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.24" - }, + "optional": true, + "os": [ + "aix" + ], "engines": { - "node": ">=6.0.0" + "node": ">=12" } }, - "node_modules/@babel/code-frame": { - "version": "7.24.2", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.24.2.tgz", - "integrity": "sha512-y5+tLQyV8pg3fsiln67BVLD1P13Eg4lh5RW9mF0zUuvLrv9uIQ4MCL+CRT+FTsBlBjcIan6PGsLcBN0m3ClUyQ==", + "node_modules/@esbuild/android-arm": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.21.5.tgz", + "integrity": "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==", + "cpu": [ + "arm" + ], "dev": true, - "dependencies": { - "@babel/highlight": "^7.24.2", - "picocolors": "^1.0.0" - }, + "optional": true, + "os": [ + "android" + ], "engines": { - "node": ">=6.9.0" + "node": ">=12" } }, - "node_modules/@babel/compat-data": { - "version": "7.24.4", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.24.4.tgz", - "integrity": "sha512-vg8Gih2MLK+kOkHJp4gBEIkyaIi00jgWot2D9QOmmfLC8jINSOzmCLta6Bvz/JSBCqnegV0L80jhxkol5GWNfQ==", + "node_modules/@esbuild/android-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz", + "integrity": "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==", + "cpu": [ + "arm64" + ], "dev": true, + "optional": true, + "os": [ + "android" + ], "engines": { - "node": ">=6.9.0" + "node": ">=12" } }, - "node_modules/@babel/core": { - "version": "7.24.5", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.24.5.tgz", - "integrity": "sha512-tVQRucExLQ02Boi4vdPp49svNGcfL2GhdTCT9aldhXgCJVAI21EtRfBettiuLUwce/7r6bFdgs6JFkcdTiFttA==", + "node_modules/@esbuild/android-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.21.5.tgz", + "integrity": "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==", + "cpu": [ + "x64" + ], "dev": true, - "dependencies": { - "@ampproject/remapping": "^2.2.0", - "@babel/code-frame": "^7.24.2", - "@babel/generator": "^7.24.5", - "@babel/helper-compilation-targets": "^7.23.6", - "@babel/helper-module-transforms": "^7.24.5", - "@babel/helpers": "^7.24.5", - "@babel/parser": "^7.24.5", - "@babel/template": "^7.24.0", - "@babel/traverse": "^7.24.5", - "@babel/types": "^7.24.5", - "convert-source-map": "^2.0.0", - "debug": "^4.1.0", - "gensync": "^1.0.0-beta.2", - "json5": "^2.2.3", - "semver": "^6.3.1" - }, + "optional": true, + "os": [ + "android" + ], "engines": { - "node": ">=6.9.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/babel" + "node": ">=12" } }, - "node_modules/@babel/generator": { - "version": "7.24.5", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.24.5.tgz", - "integrity": "sha512-x32i4hEXvr+iI0NEoEfDKzlemF8AmtOP8CcrRaEcpzysWuoEb1KknpcvMsHKPONoKZiDuItklgWhB18xEhr9PA==", + "node_modules/@esbuild/darwin-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz", + "integrity": "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==", + "cpu": [ + "arm64" + ], "dev": true, - "dependencies": { - "@babel/types": "^7.24.5", - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.25", - "jsesc": "^2.5.1" - }, + "optional": true, + "os": [ + "darwin" + ], "engines": { - "node": ">=6.9.0" + "node": ">=12" } }, - "node_modules/@babel/helper-annotate-as-pure": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.22.5.tgz", - "integrity": "sha512-LvBTxu8bQSQkcyKOU+a1btnNFQ1dMAd0R6PyW3arXes06F6QLWLIrd681bxRPIXlrMGR3XYnW9JyML7dP3qgxg==", + "node_modules/@esbuild/darwin-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz", + "integrity": "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==", + "cpu": [ + "x64" + ], "dev": true, - "dependencies": { - "@babel/types": "^7.22.5" - }, + "optional": true, + "os": [ + "darwin" + ], "engines": { - "node": ">=6.9.0" + "node": ">=12" } }, - "node_modules/@babel/helper-builder-binary-assignment-operator-visitor": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.22.15.tgz", - "integrity": "sha512-QkBXwGgaoC2GtGZRoma6kv7Szfv06khvhFav67ZExau2RaXzy8MpHSMO2PNoP2XtmQphJQRHFfg77Bq731Yizw==", + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz", + "integrity": "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==", + "cpu": [ + "arm64" + ], "dev": true, - "dependencies": { - "@babel/types": "^7.22.15" - }, + "optional": true, + "os": [ + "freebsd" + ], "engines": { - "node": ">=6.9.0" + "node": ">=12" } }, - "node_modules/@babel/helper-compilation-targets": { - "version": "7.23.6", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.23.6.tgz", - "integrity": "sha512-9JB548GZoQVmzrFgp8o7KxdgkTGm6xs9DW0o/Pim72UDjzr5ObUQ6ZzYPqA+g9OTS2bBQoctLJrky0RDCAWRgQ==", + "node_modules/@esbuild/freebsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz", + "integrity": "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==", + "cpu": [ + "x64" + ], "dev": true, - "dependencies": { - "@babel/compat-data": "^7.23.5", - "@babel/helper-validator-option": "^7.23.5", - "browserslist": "^4.22.2", - "lru-cache": "^5.1.1", - "semver": "^6.3.1" - }, + "optional": true, + "os": [ + "freebsd" + ], "engines": { - "node": ">=6.9.0" + "node": ">=12" } }, - "node_modules/@babel/helper-create-class-features-plugin": { - "version": "7.24.4", - "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.24.4.tgz", - "integrity": "sha512-lG75yeuUSVu0pIcbhiYMXBXANHrpUPaOfu7ryAzskCgKUHuAxRQI5ssrtmF0X9UXldPlvT0XM/A4F44OXRt6iQ==", + "node_modules/@esbuild/linux-arm": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz", + "integrity": "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==", + "cpu": [ + "arm" + ], "dev": true, - "dependencies": { - "@babel/helper-annotate-as-pure": "^7.22.5", - "@babel/helper-environment-visitor": "^7.22.20", - "@babel/helper-function-name": "^7.23.0", - "@babel/helper-member-expression-to-functions": "^7.23.0", - "@babel/helper-optimise-call-expression": "^7.22.5", - "@babel/helper-replace-supers": "^7.24.1", - "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5", - "@babel/helper-split-export-declaration": "^7.22.6", - "semver": "^6.3.1" - }, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" + "node": ">=12" } }, - "node_modules/@babel/helper-create-regexp-features-plugin": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.22.15.tgz", - "integrity": "sha512-29FkPLFjn4TPEa3RE7GpW+qbE8tlsu3jntNYNfcGsc49LphF1PQIiD+vMZ1z1xVOKt+93khA9tc2JBs3kBjA7w==", + "node_modules/@esbuild/linux-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz", + "integrity": "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==", + "cpu": [ + "arm64" + ], "dev": true, - "dependencies": { - "@babel/helper-annotate-as-pure": "^7.22.5", - "regexpu-core": "^5.3.1", - "semver": "^6.3.1" - }, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/helper-define-polyfill-provider": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.1.tgz", - "integrity": "sha512-o7SDgTJuvx5vLKD6SFvkydkSMBvahDKGiNJzG22IZYXhiqoe9efY7zocICBgzHV4IRg5wdgl2nEL/tulKIEIbA==", - "dev": true, - "dependencies": { - "@babel/helper-compilation-targets": "^7.22.6", - "@babel/helper-plugin-utils": "^7.22.5", - "debug": "^4.1.1", - "lodash.debounce": "^4.0.8", - "resolve": "^1.14.2" - }, - "peerDependencies": { - "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + "node": ">=12" } }, - "node_modules/@babel/helper-environment-visitor": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz", - "integrity": "sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==", + "node_modules/@esbuild/linux-ia32": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz", + "integrity": "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==", + "cpu": [ + "ia32" + ], "dev": true, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=6.9.0" + "node": ">=12" } }, - "node_modules/@babel/helper-function-name": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz", - "integrity": "sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==", + "node_modules/@esbuild/linux-loong64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz", + "integrity": "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==", + "cpu": [ + "loong64" + ], "dev": true, - "dependencies": { - "@babel/template": "^7.22.15", - "@babel/types": "^7.23.0" - }, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=6.9.0" + "node": ">=12" } }, - "node_modules/@babel/helper-hoist-variables": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz", - "integrity": "sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==", + "node_modules/@esbuild/linux-mips64el": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz", + "integrity": "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==", + "cpu": [ + "mips64el" + ], "dev": true, - "dependencies": { - "@babel/types": "^7.22.5" - }, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=6.9.0" + "node": ">=12" } }, - "node_modules/@babel/helper-member-expression-to-functions": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.23.0.tgz", - "integrity": "sha512-6gfrPwh7OuT6gZyJZvd6WbTfrqAo7vm4xCzAXOusKqq/vWdKXphTpj5klHKNmRUU6/QRGlBsyU9mAIPaWHlqJA==", + "node_modules/@esbuild/linux-ppc64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz", + "integrity": "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==", + "cpu": [ + "ppc64" + ], "dev": true, - "dependencies": { - "@babel/types": "^7.23.0" - }, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=6.9.0" + "node": ">=12" } }, - "node_modules/@babel/helper-module-imports": { - "version": "7.24.3", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.24.3.tgz", - "integrity": "sha512-viKb0F9f2s0BCS22QSF308z/+1YWKV/76mwt61NBzS5izMzDPwdq1pTrzf+Li3npBWX9KdQbkeCt1jSAM7lZqg==", + "node_modules/@esbuild/linux-riscv64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz", + "integrity": "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==", + "cpu": [ + "riscv64" + ], "dev": true, - "dependencies": { - "@babel/types": "^7.24.0" - }, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=6.9.0" + "node": ">=12" } }, - "node_modules/@babel/helper-module-transforms": { - "version": "7.24.5", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.24.5.tgz", - "integrity": "sha512-9GxeY8c2d2mdQUP1Dye0ks3VDyIMS98kt/llQ2nUId8IsWqTF0l1LkSX0/uP7l7MCDrzXS009Hyhe2gzTiGW8A==", + "node_modules/@esbuild/linux-s390x": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz", + "integrity": "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==", + "cpu": [ + "s390x" + ], "dev": true, - "dependencies": { - "@babel/helper-environment-visitor": "^7.22.20", - "@babel/helper-module-imports": "^7.24.3", - "@babel/helper-simple-access": "^7.24.5", - "@babel/helper-split-export-declaration": "^7.24.5", - "@babel/helper-validator-identifier": "^7.24.5" - }, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" + "node": ">=12" } }, - "node_modules/@babel/helper-optimise-call-expression": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.22.5.tgz", - "integrity": "sha512-HBwaojN0xFRx4yIvpwGqxiV2tUfl7401jlok564NgB9EHS1y6QT17FmKWm4ztqjeVdXLuC4fSvHc5ePpQjoTbw==", + "node_modules/@esbuild/linux-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz", + "integrity": "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==", + "cpu": [ + "x64" + ], "dev": true, - "dependencies": { - "@babel/types": "^7.22.5" - }, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=6.9.0" + "node": ">=12" } }, - "node_modules/@babel/helper-plugin-utils": { - "version": "7.24.0", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.0.tgz", - "integrity": "sha512-9cUznXMG0+FxRuJfvL82QlTqIzhVW9sL0KjMPHhAOOvpQGL8QtdxnBKILjBqxlHyliz0yCa1G903ZXI/FuHy2w==", + "node_modules/@esbuild/netbsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz", + "integrity": "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==", + "cpu": [ + "x64" + ], "dev": true, + "optional": true, + "os": [ + "netbsd" + ], "engines": { - "node": ">=6.9.0" + "node": ">=12" } }, - "node_modules/@babel/helper-remap-async-to-generator": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.22.20.tgz", - "integrity": "sha512-pBGyV4uBqOns+0UvhsTO8qgl8hO89PmiDYv+/COyp1aeMcmfrfruz+/nCMFiYyFF/Knn0yfrC85ZzNFjembFTw==", + "node_modules/@esbuild/openbsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz", + "integrity": "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==", + "cpu": [ + "x64" + ], "dev": true, - "dependencies": { - "@babel/helper-annotate-as-pure": "^7.22.5", - "@babel/helper-environment-visitor": "^7.22.20", - "@babel/helper-wrap-function": "^7.22.20" - }, + "optional": true, + "os": [ + "openbsd" + ], "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" + "node": ">=12" } }, - "node_modules/@babel/helper-replace-supers": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.24.1.tgz", - "integrity": "sha512-QCR1UqC9BzG5vZl8BMicmZ28RuUBnHhAMddD8yHFHDRH9lLTZ9uUPehX8ctVPT8l0TKblJidqcgUUKGVrePleQ==", + "node_modules/@esbuild/sunos-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz", + "integrity": "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==", + "cpu": [ + "x64" + ], "dev": true, - "dependencies": { - "@babel/helper-environment-visitor": "^7.22.20", - "@babel/helper-member-expression-to-functions": "^7.23.0", - "@babel/helper-optimise-call-expression": "^7.22.5" - }, + "optional": true, + "os": [ + "sunos" + ], "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" + "node": ">=12" } }, - "node_modules/@babel/helper-simple-access": { - "version": "7.24.5", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.24.5.tgz", - "integrity": "sha512-uH3Hmf5q5n7n8mz7arjUlDOCbttY/DW4DYhE6FUsjKJ/oYC1kQQUvwEQWxRwUpX9qQKRXeqLwWxrqilMrf32sQ==", + "node_modules/@esbuild/win32-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz", + "integrity": "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==", + "cpu": [ + "arm64" + ], "dev": true, - "dependencies": { - "@babel/types": "^7.24.5" - }, + "optional": true, + "os": [ + "win32" + ], "engines": { - "node": ">=6.9.0" + "node": ">=12" } }, - "node_modules/@babel/helper-skip-transparent-expression-wrappers": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.22.5.tgz", - "integrity": "sha512-tK14r66JZKiC43p8Ki33yLBVJKlQDFoA8GYN67lWCDCqoL6EMMSuM9b+Iff2jHaM/RRFYl7K+iiru7hbRqNx8Q==", + "node_modules/@esbuild/win32-ia32": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz", + "integrity": "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==", + "cpu": [ + "ia32" + ], "dev": true, - "dependencies": { - "@babel/types": "^7.22.5" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-split-export-declaration": { - "version": "7.24.5", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.24.5.tgz", - "integrity": "sha512-5CHncttXohrHk8GWOFCcCl4oRD9fKosWlIRgWm4ql9VYioKm52Mk2xsmoohvm7f3JoiLSM5ZgJuRaf5QZZYd3Q==", - "dev": true, - "dependencies": { - "@babel/types": "^7.24.5" - }, + "optional": true, + "os": [ + "win32" + ], "engines": { - "node": ">=6.9.0" + "node": ">=12" } }, - "node_modules/@babel/helper-string-parser": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.24.1.tgz", - "integrity": "sha512-2ofRCjnnA9y+wk8b9IAREroeUP02KHp431N2mhKniy2yKIDKpbrHv9eXwm8cBeWQYcJmzv5qKCu65P47eCF7CQ==", + "node_modules/@esbuild/win32-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz", + "integrity": "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==", + "cpu": [ + "x64" + ], "dev": true, + "optional": true, + "os": [ + "win32" + ], "engines": { - "node": ">=6.9.0" + "node": ">=12" } }, - "node_modules/@babel/helper-validator-identifier": { - "version": "7.24.5", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.5.tgz", - "integrity": "sha512-3q93SSKX2TWCG30M2G2kwaKeTYgEUp5Snjuj8qm729SObL6nbtUldAi37qbxkD5gg3xnBio+f9nqpSepGZMvxA==", + "node_modules/@eslint-community/eslint-utils": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", + "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", "dev": true, + "dependencies": { + "eslint-visitor-keys": "^3.3.0" + }, "engines": { - "node": ">=6.9.0" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" } }, - "node_modules/@babel/helper-validator-option": { - "version": "7.23.5", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.23.5.tgz", - "integrity": "sha512-85ttAOMLsr53VgXkTbkx8oA6YTfT4q7/HzXSLEYmjcSTJPMPQtvq1BD79Byep5xMUYbGRzEpDsjUf3dyp54IKw==", + "node_modules/@eslint-community/regexpp": { + "version": "4.10.0", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.10.0.tgz", + "integrity": "sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==", "dev": true, "engines": { - "node": ">=6.9.0" + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" } }, - "node_modules/@babel/helper-wrap-function": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.22.20.tgz", - "integrity": "sha512-pms/UwkOpnQe/PDAEdV/d7dVCoBbB+R4FvYoHGZz+4VPcg7RtYy2KP7S2lbuWM6FCSgob5wshfGESbC/hzNXZw==", + "node_modules/@eslint/eslintrc": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", + "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", "dev": true, "dependencies": { - "@babel/helper-function-name": "^7.22.5", - "@babel/template": "^7.22.15", - "@babel/types": "^7.22.19" + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.6.0", + "globals": "^13.19.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" }, "engines": { - "node": ">=6.9.0" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, - "node_modules/@babel/helpers": { - "version": "7.24.5", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.24.5.tgz", - "integrity": "sha512-CiQmBMMpMQHwM5m01YnrM6imUG1ebgYJ+fAIW4FZe6m4qHTPaRHti+R8cggAwkdz4oXhtO4/K9JWlh+8hIfR2Q==", + "node_modules/@eslint/eslintrc/node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, + "node_modules/@eslint/eslintrc/node_modules/globals": { + "version": "13.24.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", + "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", "dev": true, "dependencies": { - "@babel/template": "^7.24.0", - "@babel/traverse": "^7.24.5", - "@babel/types": "^7.24.5" + "type-fest": "^0.20.2" }, "engines": { - "node": ">=6.9.0" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@babel/highlight": { - "version": "7.24.2", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.24.2.tgz", - "integrity": "sha512-Yac1ao4flkTxTteCDZLEvdxg2fZfz1v8M4QpaGypq/WPDqg3ijHYbDfs+LG5hvzSoqaSZ9/Z9lKSP3CjZjv+pA==", + "node_modules/@eslint/eslintrc/node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", "dev": true, "dependencies": { - "@babel/helper-validator-identifier": "^7.22.20", - "chalk": "^2.4.2", - "js-tokens": "^4.0.0", - "picocolors": "^1.0.0" + "argparse": "^2.0.1" }, - "engines": { - "node": ">=6.9.0" + "bin": { + "js-yaml": "bin/js-yaml.js" } }, - "node_modules/@babel/parser": { - "version": "7.24.5", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.24.5.tgz", - "integrity": "sha512-EOv5IK8arwh3LI47dz1b0tKUb/1uhHAnHJOrjgtQMIpu1uXd9mlFrJg9IUgGUgZ41Ch0K8REPTYpO7B76b4vJg==", + "node_modules/@eslint/js": { + "version": "8.57.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.0.tgz", + "integrity": "sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==", "dev": true, - "bin": { - "parser": "bin/babel-parser.js" - }, "engines": { - "node": ">=6.0.0" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, - "node_modules/@babel/plugin-bugfix-firefox-class-in-computed-class-key": { - "version": "7.24.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-firefox-class-in-computed-class-key/-/plugin-bugfix-firefox-class-in-computed-class-key-7.24.4.tgz", - "integrity": "sha512-qpl6vOOEEzTLLcsuqYYo8yDtrTocmu2xkGvgNebvPjT9DTtfFYGmgDqY+rBYXNlqL4s9qLDn6xkrJv4RxAPiTA==", + "node_modules/@humanwhocodes/config-array": { + "version": "0.11.14", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz", + "integrity": "sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==", "dev": true, "dependencies": { - "@babel/helper-environment-visitor": "^7.22.20", - "@babel/helper-plugin-utils": "^7.24.0" + "@humanwhocodes/object-schema": "^2.0.2", + "debug": "^4.3.1", + "minimatch": "^3.0.5" }, "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" + "node": ">=10.10.0" } }, - "node_modules/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.24.1.tgz", - "integrity": "sha512-y4HqEnkelJIOQGd+3g1bTeKsA5c6qM7eOn7VggGVbBc0y8MLSKHacwcIE2PplNlQSj0PqS9rrXL/nkPVK+kUNg==", + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.0" - }, "engines": { - "node": ">=6.9.0" + "node": ">=12.22" }, - "peerDependencies": { - "@babel/core": "^7.0.0" + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" } }, - "node_modules/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.24.1.tgz", - "integrity": "sha512-Hj791Ii4ci8HqnaKHAlLNs+zaLXb0EzSDhiAWp5VNlyvCNymYfacs64pxTxbH1znW/NcArSmwpmG9IKE/TUVVQ==", + "node_modules/@humanwhocodes/object-schema": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz", + "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", + "dev": true + }, + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.24.0", - "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5", - "@babel/plugin-transform-optional-chaining": "^7.24.1" + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" }, "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.13.0" + "node": ">=12" } }, - "node_modules/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.24.1.tgz", - "integrity": "sha512-m9m/fXsXLiHfwdgydIFnpk+7jlVbnvlK5B2EKiPdLUb6WX654ZaaEWJUjk8TftRbZpK0XibovlLWX4KIZhV6jw==", + "node_modules/@isaacs/cliui/node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", "dev": true, - "dependencies": { - "@babel/helper-environment-visitor": "^7.22.20", - "@babel/helper-plugin-utils": "^7.24.0" - }, "engines": { - "node": ">=6.9.0" + "node": ">=12" }, - "peerDependencies": { - "@babel/core": "^7.0.0" + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" } }, - "node_modules/@babel/plugin-proposal-private-property-in-object": { - "version": "7.21.0-placeholder-for-preset-env.2", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0-placeholder-for-preset-env.2.tgz", - "integrity": "sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==", + "node_modules/@isaacs/cliui/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", "dev": true, "engines": { - "node": ">=6.9.0" + "node": ">=12" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/@babel/plugin-syntax-async-generators": { - "version": "7.8.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", - "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } + "node_modules/@isaacs/cliui/node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "dev": true }, - "node_modules/@babel/plugin-syntax-class-properties": { - "version": "7.12.13", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", - "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", + "node_modules/@isaacs/cliui/node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.12.13" + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@babel/plugin-syntax-class-static-block": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz", - "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==", + "node_modules/@isaacs/cliui/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5" + "ansi-regex": "^6.0.1" }, "engines": { - "node": ">=6.9.0" + "node": ">=12" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" } }, - "node_modules/@babel/plugin-syntax-dynamic-import": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz", - "integrity": "sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==", + "node_modules/@isaacs/cliui/node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, - "node_modules/@babel/plugin-syntax-export-namespace-from": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz", - "integrity": "sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==", + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", + "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.8.3" + "@jridgewell/set-array": "^1.2.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.24" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "engines": { + "node": ">=6.0.0" } }, - "node_modules/@babel/plugin-syntax-import-assertions": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.24.1.tgz", - "integrity": "sha512-IuwnI5XnuF189t91XbxmXeCDz3qs6iDRO7GJ++wcfgeXNs/8FmIlKcpDSXNVyuLQxlwvskmI3Ct73wUODkJBlQ==", + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.0" - }, "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">=6.0.0" } }, - "node_modules/@babel/plugin-syntax-import-attributes": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.24.1.tgz", - "integrity": "sha512-zhQTMH0X2nVLnb04tz+s7AMuasX8U0FnpE+nHTOhSOINjWMnopoZTxtIKsd45n4GQ/HIZLyfIpoul8e2m0DnRA==", + "node_modules/@jridgewell/set-array": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", + "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.0" - }, "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">=6.0.0" } }, - "node_modules/@babel/plugin-syntax-import-meta": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", - "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.4.15", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", + "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", + "dev": true + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.10.4" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" } }, - "node_modules/@babel/plugin-syntax-json-strings": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", - "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" + "node_modules/@jspm/core": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@jspm/core/-/core-2.0.1.tgz", + "integrity": "sha512-Lg3PnLp0QXpxwLIAuuJboLeRaIhrgJjeuh797QADg3xz8wGLugQOS5DpsE8A6i6Adgzf+bacllkKZG3J0tGfDw==", + "dev": true + }, + "node_modules/@microsoft/api-extractor": { + "version": "7.47.0", + "resolved": "https://registry.npmjs.org/@microsoft/api-extractor/-/api-extractor-7.47.0.tgz", + "integrity": "sha512-LT8yvcWNf76EpDC+8/ArTVSYePvuDQ+YbAUrsTcpg3ptiZ93HIcMCozP/JOxDt+rrsFfFHcpfoselKfPyRI0GQ==", + "dev": true, + "dependencies": { + "@microsoft/api-extractor-model": "7.29.2", + "@microsoft/tsdoc": "~0.15.0", + "@microsoft/tsdoc-config": "~0.17.0", + "@rushstack/node-core-library": "5.4.1", + "@rushstack/rig-package": "0.5.2", + "@rushstack/terminal": "0.13.0", + "@rushstack/ts-command-line": "4.22.0", + "lodash": "~4.17.15", + "minimatch": "~3.0.3", + "resolve": "~1.22.1", + "semver": "~7.5.4", + "source-map": "~0.6.1", + "typescript": "5.4.2" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "bin": { + "api-extractor": "bin/api-extractor" } }, - "node_modules/@babel/plugin-syntax-logical-assignment-operators": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", - "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", + "node_modules/@microsoft/api-extractor-model": { + "version": "7.29.2", + "resolved": "https://registry.npmjs.org/@microsoft/api-extractor-model/-/api-extractor-model-7.29.2.tgz", + "integrity": "sha512-hAYajOjQan3uslhKJRwvvHIdLJ+ZByKqdSsJ/dgHFxPtEbdKpzMDO8zuW4K5gkSMYl5D0LbNwxkhxr51P2zsmw==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.10.4" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "@microsoft/tsdoc": "~0.15.0", + "@microsoft/tsdoc-config": "~0.17.0", + "@rushstack/node-core-library": "5.4.1" } }, - "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", - "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", + "node_modules/@microsoft/api-extractor/node_modules/minimatch": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.8.tgz", + "integrity": "sha512-6FsRAQsxQ61mw+qP1ZzbL9Bc78x2p5OqNgNpnoAFLTrX8n5Kxph0CsnhmKKNXTWjXqU5L0pGPR7hYk+XWZr60Q==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" + "brace-expansion": "^1.1.7" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "engines": { + "node": "*" } }, - "node_modules/@babel/plugin-syntax-numeric-separator": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", - "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", + "node_modules/@microsoft/api-extractor/node_modules/typescript": { + "version": "5.4.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.2.tgz", + "integrity": "sha512-+2/g0Fds1ERlP6JsakQQDXjZdZMM+rqpamFZJEKh4kwTIn3iDkgKtby0CeNd5ATNZ4Ry1ax15TMx0W2V+miizQ==", "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.10.4" + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "engines": { + "node": ">=14.17" } }, - "node_modules/@babel/plugin-syntax-object-rest-spread": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", - "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", + "node_modules/@microsoft/tsdoc": { + "version": "0.15.0", + "resolved": "https://registry.npmjs.org/@microsoft/tsdoc/-/tsdoc-0.15.0.tgz", + "integrity": "sha512-HZpPoABogPvjeJOdzCOSJsXeL/SMCBgBZMVC3X3d7YYp2gf31MfxhUoYUNwf1ERPJOnQc0wkFn9trqI6ZEdZuA==", + "dev": true + }, + "node_modules/@microsoft/tsdoc-config": { + "version": "0.17.0", + "resolved": "https://registry.npmjs.org/@microsoft/tsdoc-config/-/tsdoc-config-0.17.0.tgz", + "integrity": "sha512-v/EYRXnCAIHxOHW+Plb6OWuUoMotxTN0GLatnpOb1xq0KuTNw/WI3pamJx/UbsoJP5k9MCw1QxvvhPcF9pH3Zg==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "@microsoft/tsdoc": "0.15.0", + "ajv": "~8.12.0", + "jju": "~1.4.0", + "resolve": "~1.22.2" } }, - "node_modules/@babel/plugin-syntax-optional-catch-binding": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", - "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", + "node_modules/@microsoft/tsdoc-config/node_modules/ajv": { + "version": "8.12.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", + "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" } }, - "node_modules/@babel/plugin-syntax-optional-chaining": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", - "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", + "node_modules/@microsoft/tsdoc-config/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "engines": { + "node": ">= 8" } }, - "node_modules/@babel/plugin-syntax-private-property-in-object": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz", - "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==", + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5" - }, "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">= 8" } }, - "node_modules/@babel/plugin-syntax-top-level-await": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", - "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5" + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" }, "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">= 8" } }, - "node_modules/@babel/plugin-syntax-unicode-sets-regex": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-unicode-sets-regex/-/plugin-syntax-unicode-sets-regex-7.18.6.tgz", - "integrity": "sha512-727YkEAPwSIQTv5im8QHz3upqp92JTWhidIC81Tdx4VJYIte/VndKf1qKrfnnhPLiPghStWfvC/iFaMCQu7Nqg==", + "node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", "dev": true, - "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6" - }, + "optional": true, "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" + "node": ">=14" } }, - "node_modules/@babel/plugin-transform-arrow-functions": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.24.1.tgz", - "integrity": "sha512-ngT/3NkRhsaep9ck9uj2Xhv9+xB1zShY3tM3g6om4xxCELwCDN4g4Aq5dRn48+0hasAql7s2hdBOysCfNpr4fw==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.0" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-async-generator-functions": { - "version": "7.24.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.24.3.tgz", - "integrity": "sha512-Qe26CMYVjpQxJ8zxM1340JFNjZaF+ISWpr1Kt/jGo+ZTUzKkfw/pphEWbRCb+lmSM6k/TOgfYLvmbHkUQ0asIg==", - "dev": true, - "dependencies": { - "@babel/helper-environment-visitor": "^7.22.20", - "@babel/helper-plugin-utils": "^7.24.0", - "@babel/helper-remap-async-to-generator": "^7.22.20", - "@babel/plugin-syntax-async-generators": "^7.8.4" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-async-to-generator": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.24.1.tgz", - "integrity": "sha512-AawPptitRXp1y0n4ilKcGbRYWfbbzFWz2NqNu7dacYDtFtz0CMjG64b3LQsb3KIgnf4/obcUL78hfaOS7iCUfw==", - "dev": true, - "dependencies": { - "@babel/helper-module-imports": "^7.24.1", - "@babel/helper-plugin-utils": "^7.24.0", - "@babel/helper-remap-async-to-generator": "^7.22.20" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-block-scoped-functions": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.24.1.tgz", - "integrity": "sha512-TWWC18OShZutrv9C6mye1xwtam+uNi2bnTOCBUd5sZxyHOiWbU6ztSROofIMrK84uweEZC219POICK/sTYwfgg==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.0" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-block-scoping": { - "version": "7.24.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.24.4.tgz", - "integrity": "sha512-nIFUZIpGKDf9O9ttyRXpHFpKC+X3Y5mtshZONuEUYBomAKoM4y029Jr+uB1bHGPhNmK8YXHevDtKDOLmtRrp6g==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.0" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-class-properties": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.24.1.tgz", - "integrity": "sha512-OMLCXi0NqvJfORTaPQBwqLXHhb93wkBKZ4aNwMl6WtehO7ar+cmp+89iPEQPqxAnxsOKTaMcs3POz3rKayJ72g==", - "dev": true, - "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.24.1", - "@babel/helper-plugin-utils": "^7.24.0" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-class-static-block": { - "version": "7.24.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.24.4.tgz", - "integrity": "sha512-B8q7Pz870Hz/q9UgP8InNpY01CSLDSCyqX7zcRuv3FcPl87A2G17lASroHWaCtbdIcbYzOZ7kWmXFKbijMSmFg==", - "dev": true, - "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.24.4", - "@babel/helper-plugin-utils": "^7.24.0", - "@babel/plugin-syntax-class-static-block": "^7.14.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.12.0" - } - }, - "node_modules/@babel/plugin-transform-classes": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.24.1.tgz", - "integrity": "sha512-ZTIe3W7UejJd3/3R4p7ScyyOoafetUShSf4kCqV0O7F/RiHxVj/wRaRnQlrGwflvcehNA8M42HkAiEDYZu2F1Q==", - "dev": true, - "dependencies": { - "@babel/helper-annotate-as-pure": "^7.22.5", - "@babel/helper-compilation-targets": "^7.23.6", - "@babel/helper-environment-visitor": "^7.22.20", - "@babel/helper-function-name": "^7.23.0", - "@babel/helper-plugin-utils": "^7.24.0", - "@babel/helper-replace-supers": "^7.24.1", - "@babel/helper-split-export-declaration": "^7.22.6", - "globals": "^11.1.0" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-computed-properties": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.24.1.tgz", - "integrity": "sha512-5pJGVIUfJpOS+pAqBQd+QMaTD2vCL/HcePooON6pDpHgRp4gNRmzyHTPIkXntwKsq3ayUFVfJaIKPw2pOkOcTw==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.0", - "@babel/template": "^7.24.0" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-destructuring": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.24.1.tgz", - "integrity": "sha512-ow8jciWqNxR3RYbSNVuF4U2Jx130nwnBnhRw6N6h1bOejNkABmcI5X5oz29K4alWX7vf1C+o6gtKXikzRKkVdw==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.0" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-dotall-regex": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.24.1.tgz", - "integrity": "sha512-p7uUxgSoZwZ2lPNMzUkqCts3xlp8n+o05ikjy7gbtFJSt9gdU88jAmtfmOxHM14noQXBxfgzf2yRWECiNVhTCw==", - "dev": true, - "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.22.15", - "@babel/helper-plugin-utils": "^7.24.0" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-duplicate-keys": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.24.1.tgz", - "integrity": "sha512-msyzuUnvsjsaSaocV6L7ErfNsa5nDWL1XKNnDePLgmz+WdU4w/J8+AxBMrWfi9m4IxfL5sZQKUPQKDQeeAT6lA==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.0" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-dynamic-import": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.24.1.tgz", - "integrity": "sha512-av2gdSTyXcJVdI+8aFZsCAtR29xJt0S5tas+Ef8NvBNmD1a+N/3ecMLeMBgfcK+xzsjdLDT6oHt+DFPyeqUbDA==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.0", - "@babel/plugin-syntax-dynamic-import": "^7.8.3" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-exponentiation-operator": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.24.1.tgz", - "integrity": "sha512-U1yX13dVBSwS23DEAqU+Z/PkwE9/m7QQy8Y9/+Tdb8UWYaGNDYwTLi19wqIAiROr8sXVum9A/rtiH5H0boUcTw==", - "dev": true, - "dependencies": { - "@babel/helper-builder-binary-assignment-operator-visitor": "^7.22.15", - "@babel/helper-plugin-utils": "^7.24.0" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-export-namespace-from": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.24.1.tgz", - "integrity": "sha512-Ft38m/KFOyzKw2UaJFkWG9QnHPG/Q/2SkOrRk4pNBPg5IPZ+dOxcmkK5IyuBcxiNPyyYowPGUReyBvrvZs7IlQ==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.0", - "@babel/plugin-syntax-export-namespace-from": "^7.8.3" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-for-of": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.24.1.tgz", - "integrity": "sha512-OxBdcnF04bpdQdR3i4giHZNZQn7cm8RQKcSwA17wAAqEELo1ZOwp5FFgeptWUQXFyT9kwHo10aqqauYkRZPCAg==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.0", - "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-function-name": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.24.1.tgz", - "integrity": "sha512-BXmDZpPlh7jwicKArQASrj8n22/w6iymRnvHYYd2zO30DbE277JO20/7yXJT3QxDPtiQiOxQBbZH4TpivNXIxA==", - "dev": true, - "dependencies": { - "@babel/helper-compilation-targets": "^7.23.6", - "@babel/helper-function-name": "^7.23.0", - "@babel/helper-plugin-utils": "^7.24.0" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-json-strings": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.24.1.tgz", - "integrity": "sha512-U7RMFmRvoasscrIFy5xA4gIp8iWnWubnKkKuUGJjsuOH7GfbMkB+XZzeslx2kLdEGdOJDamEmCqOks6e8nv8DQ==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.0", - "@babel/plugin-syntax-json-strings": "^7.8.3" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-literals": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.24.1.tgz", - "integrity": "sha512-zn9pwz8U7nCqOYIiBaOxoQOtYmMODXTJnkxG4AtX8fPmnCRYWBOHD0qcpwS9e2VDSp1zNJYpdnFMIKb8jmwu6g==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.0" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-logical-assignment-operators": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.24.1.tgz", - "integrity": "sha512-OhN6J4Bpz+hIBqItTeWJujDOfNP+unqv/NJgyhlpSqgBTPm37KkMmZV6SYcOj+pnDbdcl1qRGV/ZiIjX9Iy34w==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.0", - "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-member-expression-literals": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.24.1.tgz", - "integrity": "sha512-4ojai0KysTWXzHseJKa1XPNXKRbuUrhkOPY4rEGeR+7ChlJVKxFa3H3Bz+7tWaGKgJAXUWKOGmltN+u9B3+CVg==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.0" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-modules-amd": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.24.1.tgz", - "integrity": "sha512-lAxNHi4HVtjnHd5Rxg3D5t99Xm6H7b04hUS7EHIXcUl2EV4yl1gWdqZrNzXnSrHveL9qMdbODlLF55mvgjAfaQ==", - "dev": true, - "dependencies": { - "@babel/helper-module-transforms": "^7.23.3", - "@babel/helper-plugin-utils": "^7.24.0" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-modules-commonjs": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.24.1.tgz", - "integrity": "sha512-szog8fFTUxBfw0b98gEWPaEqF42ZUD/T3bkynW/wtgx2p/XCP55WEsb+VosKceRSd6njipdZvNogqdtI4Q0chw==", - "dev": true, - "dependencies": { - "@babel/helper-module-transforms": "^7.23.3", - "@babel/helper-plugin-utils": "^7.24.0", - "@babel/helper-simple-access": "^7.22.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-modules-systemjs": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.24.1.tgz", - "integrity": "sha512-mqQ3Zh9vFO1Tpmlt8QPnbwGHzNz3lpNEMxQb1kAemn/erstyqw1r9KeOlOfo3y6xAnFEcOv2tSyrXfmMk+/YZA==", - "dev": true, - "dependencies": { - "@babel/helper-hoist-variables": "^7.22.5", - "@babel/helper-module-transforms": "^7.23.3", - "@babel/helper-plugin-utils": "^7.24.0", - "@babel/helper-validator-identifier": "^7.22.20" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-modules-umd": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.24.1.tgz", - "integrity": "sha512-tuA3lpPj+5ITfcCluy6nWonSL7RvaG0AOTeAuvXqEKS34lnLzXpDb0dcP6K8jD0zWZFNDVly90AGFJPnm4fOYg==", - "dev": true, - "dependencies": { - "@babel/helper-module-transforms": "^7.23.3", - "@babel/helper-plugin-utils": "^7.24.0" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-named-capturing-groups-regex": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.22.5.tgz", - "integrity": "sha512-YgLLKmS3aUBhHaxp5hi1WJTgOUb/NCuDHzGT9z9WTt3YG+CPRhJs6nprbStx6DnWM4dh6gt7SU3sZodbZ08adQ==", - "dev": true, - "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.22.5", - "@babel/helper-plugin-utils": "^7.22.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/plugin-transform-new-target": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.24.1.tgz", - "integrity": "sha512-/rurytBM34hYy0HKZQyA0nHbQgQNFm4Q/BOc9Hflxi2X3twRof7NaE5W46j4kQitm7SvACVRXsa6N/tSZxvPug==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.0" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-nullish-coalescing-operator": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.24.1.tgz", - "integrity": "sha512-iQ+caew8wRrhCikO5DrUYx0mrmdhkaELgFa+7baMcVuhxIkN7oxt06CZ51D65ugIb1UWRQ8oQe+HXAVM6qHFjw==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.0", - "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-numeric-separator": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.24.1.tgz", - "integrity": "sha512-7GAsGlK4cNL2OExJH1DzmDeKnRv/LXq0eLUSvudrehVA5Rgg4bIrqEUW29FbKMBRT0ztSqisv7kjP+XIC4ZMNw==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.0", - "@babel/plugin-syntax-numeric-separator": "^7.10.4" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-object-rest-spread": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.24.1.tgz", - "integrity": "sha512-XjD5f0YqOtebto4HGISLNfiNMTTs6tbkFf2TOqJlYKYmbo+mN9Dnpl4SRoofiziuOWMIyq3sZEUqLo3hLITFEA==", - "dev": true, - "dependencies": { - "@babel/helper-compilation-targets": "^7.23.6", - "@babel/helper-plugin-utils": "^7.24.0", - "@babel/plugin-syntax-object-rest-spread": "^7.8.3", - "@babel/plugin-transform-parameters": "^7.24.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-object-super": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.24.1.tgz", - "integrity": "sha512-oKJqR3TeI5hSLRxudMjFQ9re9fBVUU0GICqM3J1mi8MqlhVr6hC/ZN4ttAyMuQR6EZZIY6h/exe5swqGNNIkWQ==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.0", - "@babel/helper-replace-supers": "^7.24.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-optional-catch-binding": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.24.1.tgz", - "integrity": "sha512-oBTH7oURV4Y+3EUrf6cWn1OHio3qG/PVwO5J03iSJmBg6m2EhKjkAu/xuaXaYwWW9miYtvbWv4LNf0AmR43LUA==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.0", - "@babel/plugin-syntax-optional-catch-binding": "^7.8.3" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-optional-chaining": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.24.1.tgz", - "integrity": "sha512-n03wmDt+987qXwAgcBlnUUivrZBPZ8z1plL0YvgQalLm+ZE5BMhGm94jhxXtA1wzv1Cu2aaOv1BM9vbVttrzSg==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.0", - "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5", - "@babel/plugin-syntax-optional-chaining": "^7.8.3" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-parameters": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.24.1.tgz", - "integrity": "sha512-8Jl6V24g+Uw5OGPeWNKrKqXPDw2YDjLc53ojwfMcKwlEoETKU9rU0mHUtcg9JntWI/QYzGAXNWEcVHZ+fR+XXg==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.0" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-private-methods": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.24.1.tgz", - "integrity": "sha512-tGvisebwBO5em4PaYNqt4fkw56K2VALsAbAakY0FjTYqJp7gfdrgr7YX76Or8/cpik0W6+tj3rZ0uHU9Oil4tw==", - "dev": true, - "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.24.1", - "@babel/helper-plugin-utils": "^7.24.0" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-private-property-in-object": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.24.1.tgz", - "integrity": "sha512-pTHxDVa0BpUbvAgX3Gat+7cSciXqUcY9j2VZKTbSB6+VQGpNgNO9ailxTGHSXlqOnX1Hcx1Enme2+yv7VqP9bg==", - "dev": true, - "dependencies": { - "@babel/helper-annotate-as-pure": "^7.22.5", - "@babel/helper-create-class-features-plugin": "^7.24.1", - "@babel/helper-plugin-utils": "^7.24.0", - "@babel/plugin-syntax-private-property-in-object": "^7.14.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-property-literals": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.24.1.tgz", - "integrity": "sha512-LetvD7CrHmEx0G442gOomRr66d7q8HzzGGr4PMHGr+5YIm6++Yke+jxj246rpvsbyhJwCLxcTn6zW1P1BSenqA==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.0" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-regenerator": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.24.1.tgz", - "integrity": "sha512-sJwZBCzIBE4t+5Q4IGLaaun5ExVMRY0lYwos/jNecjMrVCygCdph3IKv0tkP5Fc87e/1+bebAmEAGBfnRD+cnw==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.0", - "regenerator-transform": "^0.15.2" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-reserved-words": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.24.1.tgz", - "integrity": "sha512-JAclqStUfIwKN15HrsQADFgeZt+wexNQ0uLhuqvqAUFoqPMjEcFCYZBhq0LUdz6dZK/mD+rErhW71fbx8RYElg==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.0" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-runtime": { - "version": "7.24.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.24.3.tgz", - "integrity": "sha512-J0BuRPNlNqlMTRJ72eVptpt9VcInbxO6iP3jaxr+1NPhC0UkKL+6oeX6VXMEYdADnuqmMmsBspt4d5w8Y/TCbQ==", - "dev": true, - "dependencies": { - "@babel/helper-module-imports": "^7.24.3", - "@babel/helper-plugin-utils": "^7.24.0", - "babel-plugin-polyfill-corejs2": "^0.4.10", - "babel-plugin-polyfill-corejs3": "^0.10.1", - "babel-plugin-polyfill-regenerator": "^0.6.1", - "semver": "^6.3.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-shorthand-properties": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.24.1.tgz", - "integrity": "sha512-LyjVB1nsJ6gTTUKRjRWx9C1s9hE7dLfP/knKdrfeH9UPtAGjYGgxIbFfx7xyLIEWs7Xe1Gnf8EWiUqfjLhInZA==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.0" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-spread": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.24.1.tgz", - "integrity": "sha512-KjmcIM+fxgY+KxPVbjelJC6hrH1CgtPmTvdXAfn3/a9CnWGSTY7nH4zm5+cjmWJybdcPSsD0++QssDsjcpe47g==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.0", - "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-sticky-regex": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.24.1.tgz", - "integrity": "sha512-9v0f1bRXgPVcPrngOQvLXeGNNVLc8UjMVfebo9ka0WF3/7+aVUHmaJVT3sa0XCzEFioPfPHZiOcYG9qOsH63cw==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.0" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-template-literals": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.24.1.tgz", - "integrity": "sha512-WRkhROsNzriarqECASCNu/nojeXCDTE/F2HmRgOzi7NGvyfYGq1NEjKBK3ckLfRgGc6/lPAqP0vDOSw3YtG34g==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.0" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-typeof-symbol": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.24.1.tgz", - "integrity": "sha512-CBfU4l/A+KruSUoW+vTQthwcAdwuqbpRNB8HQKlZABwHRhsdHZ9fezp4Sn18PeAlYxTNiLMlx4xUBV3AWfg1BA==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.0" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-unicode-escapes": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.24.1.tgz", - "integrity": "sha512-RlkVIcWT4TLI96zM660S877E7beKlQw7Ig+wqkKBiWfj0zH5Q4h50q6er4wzZKRNSYpfo6ILJ+hrJAGSX2qcNw==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.24.0" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-unicode-property-regex": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.24.1.tgz", - "integrity": "sha512-Ss4VvlfYV5huWApFsF8/Sq0oXnGO+jB+rijFEFugTd3cwSObUSnUi88djgR5528Csl0uKlrI331kRqe56Ov2Ng==", - "dev": true, - "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.22.15", - "@babel/helper-plugin-utils": "^7.24.0" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-unicode-regex": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.24.1.tgz", - "integrity": "sha512-2A/94wgZgxfTsiLaQ2E36XAOdcZmGAaEEgVmxQWwZXWkGhvoHbaqXcKnU8zny4ycpu3vNqg0L/PcCiYtHtA13g==", - "dev": true, - "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.22.15", - "@babel/helper-plugin-utils": "^7.24.0" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-unicode-sets-regex": { - "version": "7.24.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.24.1.tgz", - "integrity": "sha512-fqj4WuzzS+ukpgerpAoOnMfQXwUHFxXUZUE84oL2Kao2N8uSlvcpnAidKASgsNgzZHBsHWvcm8s9FPWUhAb8fA==", - "dev": true, - "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.22.15", - "@babel/helper-plugin-utils": "^7.24.0" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/preset-env": { - "version": "7.24.4", - "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.24.4.tgz", - "integrity": "sha512-7Kl6cSmYkak0FK/FXjSEnLJ1N9T/WA2RkMhu17gZ/dsxKJUuTYNIylahPTzqpLyJN4WhDif8X0XK1R8Wsguo/A==", - "dev": true, - "dependencies": { - "@babel/compat-data": "^7.24.4", - "@babel/helper-compilation-targets": "^7.23.6", - "@babel/helper-plugin-utils": "^7.24.0", - "@babel/helper-validator-option": "^7.23.5", - "@babel/plugin-bugfix-firefox-class-in-computed-class-key": "^7.24.4", - "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.24.1", - "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.24.1", - "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "^7.24.1", - "@babel/plugin-proposal-private-property-in-object": "7.21.0-placeholder-for-preset-env.2", - "@babel/plugin-syntax-async-generators": "^7.8.4", - "@babel/plugin-syntax-class-properties": "^7.12.13", - "@babel/plugin-syntax-class-static-block": "^7.14.5", - "@babel/plugin-syntax-dynamic-import": "^7.8.3", - "@babel/plugin-syntax-export-namespace-from": "^7.8.3", - "@babel/plugin-syntax-import-assertions": "^7.24.1", - "@babel/plugin-syntax-import-attributes": "^7.24.1", - "@babel/plugin-syntax-import-meta": "^7.10.4", - "@babel/plugin-syntax-json-strings": "^7.8.3", - "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", - "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", - "@babel/plugin-syntax-numeric-separator": "^7.10.4", - "@babel/plugin-syntax-object-rest-spread": "^7.8.3", - "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", - "@babel/plugin-syntax-optional-chaining": "^7.8.3", - "@babel/plugin-syntax-private-property-in-object": "^7.14.5", - "@babel/plugin-syntax-top-level-await": "^7.14.5", - "@babel/plugin-syntax-unicode-sets-regex": "^7.18.6", - "@babel/plugin-transform-arrow-functions": "^7.24.1", - "@babel/plugin-transform-async-generator-functions": "^7.24.3", - "@babel/plugin-transform-async-to-generator": "^7.24.1", - "@babel/plugin-transform-block-scoped-functions": "^7.24.1", - "@babel/plugin-transform-block-scoping": "^7.24.4", - "@babel/plugin-transform-class-properties": "^7.24.1", - "@babel/plugin-transform-class-static-block": "^7.24.4", - "@babel/plugin-transform-classes": "^7.24.1", - "@babel/plugin-transform-computed-properties": "^7.24.1", - "@babel/plugin-transform-destructuring": "^7.24.1", - "@babel/plugin-transform-dotall-regex": "^7.24.1", - "@babel/plugin-transform-duplicate-keys": "^7.24.1", - "@babel/plugin-transform-dynamic-import": "^7.24.1", - "@babel/plugin-transform-exponentiation-operator": "^7.24.1", - "@babel/plugin-transform-export-namespace-from": "^7.24.1", - "@babel/plugin-transform-for-of": "^7.24.1", - "@babel/plugin-transform-function-name": "^7.24.1", - "@babel/plugin-transform-json-strings": "^7.24.1", - "@babel/plugin-transform-literals": "^7.24.1", - "@babel/plugin-transform-logical-assignment-operators": "^7.24.1", - "@babel/plugin-transform-member-expression-literals": "^7.24.1", - "@babel/plugin-transform-modules-amd": "^7.24.1", - "@babel/plugin-transform-modules-commonjs": "^7.24.1", - "@babel/plugin-transform-modules-systemjs": "^7.24.1", - "@babel/plugin-transform-modules-umd": "^7.24.1", - "@babel/plugin-transform-named-capturing-groups-regex": "^7.22.5", - "@babel/plugin-transform-new-target": "^7.24.1", - "@babel/plugin-transform-nullish-coalescing-operator": "^7.24.1", - "@babel/plugin-transform-numeric-separator": "^7.24.1", - "@babel/plugin-transform-object-rest-spread": "^7.24.1", - "@babel/plugin-transform-object-super": "^7.24.1", - "@babel/plugin-transform-optional-catch-binding": "^7.24.1", - "@babel/plugin-transform-optional-chaining": "^7.24.1", - "@babel/plugin-transform-parameters": "^7.24.1", - "@babel/plugin-transform-private-methods": "^7.24.1", - "@babel/plugin-transform-private-property-in-object": "^7.24.1", - "@babel/plugin-transform-property-literals": "^7.24.1", - "@babel/plugin-transform-regenerator": "^7.24.1", - "@babel/plugin-transform-reserved-words": "^7.24.1", - "@babel/plugin-transform-shorthand-properties": "^7.24.1", - "@babel/plugin-transform-spread": "^7.24.1", - "@babel/plugin-transform-sticky-regex": "^7.24.1", - "@babel/plugin-transform-template-literals": "^7.24.1", - "@babel/plugin-transform-typeof-symbol": "^7.24.1", - "@babel/plugin-transform-unicode-escapes": "^7.24.1", - "@babel/plugin-transform-unicode-property-regex": "^7.24.1", - "@babel/plugin-transform-unicode-regex": "^7.24.1", - "@babel/plugin-transform-unicode-sets-regex": "^7.24.1", - "@babel/preset-modules": "0.1.6-no-external-plugins", - "babel-plugin-polyfill-corejs2": "^0.4.10", - "babel-plugin-polyfill-corejs3": "^0.10.4", - "babel-plugin-polyfill-regenerator": "^0.6.1", - "core-js-compat": "^3.31.0", - "semver": "^6.3.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/preset-modules": { - "version": "0.1.6-no-external-plugins", - "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.6-no-external-plugins.tgz", - "integrity": "sha512-HrcgcIESLm9aIR842yhJ5RWan/gebQUJ6E/E5+rf0y9o6oj7w0Br+sWuL6kEQ/o/AdfvR1Je9jG18/gnpwjEyA==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/types": "^7.4.4", - "esutils": "^2.0.2" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0 || ^8.0.0-0 <8.0.0" - } - }, - "node_modules/@babel/regjsgen": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/@babel/regjsgen/-/regjsgen-0.8.0.tgz", - "integrity": "sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA==", - "dev": true - }, - "node_modules/@babel/runtime": { - "version": "7.24.4", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.24.4.tgz", - "integrity": "sha512-dkxf7+hn8mFBwKjs9bvBlArzLVxVbS8usaPUDd5p2a9JCL9tB8OaOVN1isD4+Xyk4ns89/xeOmbQvgdK7IIVdA==", + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.18.0.tgz", + "integrity": "sha512-Tya6xypR10giZV1XzxmH5wr25VcZSncG0pZIjfePT0OVBvqNEurzValetGNarVrGiq66EBVAFn15iYX4w6FKgQ==", + "cpu": [ + "arm" + ], "dev": true, - "dependencies": { - "regenerator-runtime": "^0.14.0" - }, - "engines": { - "node": ">=6.9.0" - } + "optional": true, + "os": [ + "android" + ] }, - "node_modules/@babel/template": { - "version": "7.24.0", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.24.0.tgz", - "integrity": "sha512-Bkf2q8lMB0AFpX0NFEqSbx1OkTHf0f+0j82mkw+ZpzBnkk7e9Ql0891vlfgi+kHwOk8tQjiQHpqh4LaSa0fKEA==", + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.18.0.tgz", + "integrity": "sha512-avCea0RAP03lTsDhEyfy+hpfr85KfyTctMADqHVhLAF3MlIkq83CP8UfAHUssgXTYd+6er6PaAhx/QGv4L1EiA==", + "cpu": [ + "arm64" + ], "dev": true, - "dependencies": { - "@babel/code-frame": "^7.23.5", - "@babel/parser": "^7.24.0", - "@babel/types": "^7.24.0" - }, - "engines": { - "node": ">=6.9.0" - } + "optional": true, + "os": [ + "android" + ] }, - "node_modules/@babel/traverse": { - "version": "7.24.5", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.24.5.tgz", - "integrity": "sha512-7aaBLeDQ4zYcUFDUD41lJc1fG8+5IU9DaNSJAgal866FGvmD5EbWQgnEC6kO1gGLsX0esNkfnJSndbTXA3r7UA==", + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.18.0.tgz", + "integrity": "sha512-IWfdwU7KDSm07Ty0PuA/W2JYoZ4iTj3TUQjkVsO/6U+4I1jN5lcR71ZEvRh52sDOERdnNhhHU57UITXz5jC1/w==", + "cpu": [ + "arm64" + ], "dev": true, - "dependencies": { - "@babel/code-frame": "^7.24.2", - "@babel/generator": "^7.24.5", - "@babel/helper-environment-visitor": "^7.22.20", - "@babel/helper-function-name": "^7.23.0", - "@babel/helper-hoist-variables": "^7.22.5", - "@babel/helper-split-export-declaration": "^7.24.5", - "@babel/parser": "^7.24.5", - "@babel/types": "^7.24.5", - "debug": "^4.3.1", - "globals": "^11.1.0" - }, - "engines": { - "node": ">=6.9.0" - } + "optional": true, + "os": [ + "darwin" + ] }, - "node_modules/@babel/types": { - "version": "7.24.5", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.24.5.tgz", - "integrity": "sha512-6mQNsaLeXTw0nxYUYu+NSa4Hx4BlF1x1x8/PMFbiR+GBSr+2DkECc69b8hgy2frEodNcvPffeH8YfWd3LI6jhQ==", + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.18.0.tgz", + "integrity": "sha512-n2LMsUz7Ynu7DoQrSQkBf8iNrjOGyPLrdSg802vk6XT3FtsgX6JbE8IHRvposskFm9SNxzkLYGSq9QdpLYpRNA==", + "cpu": [ + "x64" + ], "dev": true, - "dependencies": { - "@babel/helper-string-parser": "^7.24.1", - "@babel/helper-validator-identifier": "^7.24.5", - "to-fast-properties": "^2.0.0" - }, - "engines": { - "node": ">=6.9.0" - } + "optional": true, + "os": [ + "darwin" + ] }, - "node_modules/@esbuild/aix-ppc64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.20.2.tgz", - "integrity": "sha512-D+EBOJHXdNZcLJRBkhENNG8Wji2kgc9AZ9KiPr1JuZjsNtyHzrsfLRrY0tk2H2aoFu6RANO1y1iPPUCDYWkb5g==", + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.18.0.tgz", + "integrity": "sha512-C/zbRYRXFjWvz9Z4haRxcTdnkPt1BtCkz+7RtBSuNmKzMzp3ZxdM28Mpccn6pt28/UWUCTXa+b0Mx1k3g6NOMA==", "cpu": [ - "ppc64" + "arm" ], "dev": true, "optional": true, "os": [ - "aix" - ], - "engines": { - "node": ">=12" - } + "linux" + ] }, - "node_modules/@esbuild/android-arm": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.20.2.tgz", - "integrity": "sha512-t98Ra6pw2VaDhqNWO2Oph2LXbz/EJcnLmKLGBJwEwXX/JAN83Fym1rU8l0JUWK6HkIbWONCSSatf4sf2NBRx/w==", + "node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.18.0.tgz", + "integrity": "sha512-l3m9ewPgjQSXrUMHg93vt0hYCGnrMOcUpTz6FLtbwljo2HluS4zTXFy2571YQbisTnfTKPZ01u/ukJdQTLGh9A==", "cpu": [ "arm" ], "dev": true, "optional": true, "os": [ - "android" - ], - "engines": { - "node": ">=12" - } + "linux" + ] }, - "node_modules/@esbuild/android-arm64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.20.2.tgz", - "integrity": "sha512-mRzjLacRtl/tWU0SvD8lUEwb61yP9cqQo6noDZP/O8VkwafSYwZ4yWy24kan8jE/IMERpYncRt2dw438LP3Xmg==", + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.18.0.tgz", + "integrity": "sha512-rJ5D47d8WD7J+7STKdCUAgmQk49xuFrRi9pZkWoRD1UeSMakbcepWXPF8ycChBoAqs1pb2wzvbY6Q33WmN2ftw==", "cpu": [ "arm64" ], "dev": true, "optional": true, "os": [ - "android" - ], - "engines": { - "node": ">=12" - } + "linux" + ] }, - "node_modules/@esbuild/android-x64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.20.2.tgz", - "integrity": "sha512-btzExgV+/lMGDDa194CcUQm53ncxzeBrWJcncOBxuC6ndBkKxnHdFJn86mCIgTELsooUmwUm9FkhSp5HYu00Rg==", + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.18.0.tgz", + "integrity": "sha512-be6Yx37b24ZwxQ+wOQXXLZqpq4jTckJhtGlWGZs68TgdKXJgw54lUUoFYrg6Zs/kjzAQwEwYbp8JxZVzZLRepQ==", "cpu": [ - "x64" + "arm64" ], "dev": true, "optional": true, "os": [ - "android" - ], - "engines": { - "node": ">=12" - } + "linux" + ] }, - "node_modules/@esbuild/darwin-arm64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.20.2.tgz", - "integrity": "sha512-4J6IRT+10J3aJH3l1yzEg9y3wkTDgDk7TSDFX+wKFiWjqWp/iCfLIYzGyasx9l0SAFPT1HwSCR+0w/h1ES/MjA==", + "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.18.0.tgz", + "integrity": "sha512-hNVMQK+qrA9Todu9+wqrXOHxFiD5YmdEi3paj6vP02Kx1hjd2LLYR2eaN7DsEshg09+9uzWi2W18MJDlG0cxJA==", "cpu": [ - "arm64" + "ppc64" ], "dev": true, "optional": true, "os": [ - "darwin" - ], - "engines": { - "node": ">=12" - } + "linux" + ] }, - "node_modules/@esbuild/darwin-x64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.20.2.tgz", - "integrity": "sha512-tBcXp9KNphnNH0dfhv8KYkZhjc+H3XBkF5DKtswJblV7KlT9EI2+jeA8DgBjp908WEuYll6pF+UStUCfEpdysA==", + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.18.0.tgz", + "integrity": "sha512-ROCM7i+m1NfdrsmvwSzoxp9HFtmKGHEqu5NNDiZWQtXLA8S5HBCkVvKAxJ8U+CVctHwV2Gb5VUaK7UAkzhDjlg==", "cpu": [ - "x64" + "riscv64" ], "dev": true, "optional": true, "os": [ - "darwin" - ], - "engines": { - "node": ">=12" - } + "linux" + ] }, - "node_modules/@esbuild/freebsd-arm64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.20.2.tgz", - "integrity": "sha512-d3qI41G4SuLiCGCFGUrKsSeTXyWG6yem1KcGZVS+3FYlYhtNoNgYrWcvkOoaqMhwXSMrZRl69ArHsGJ9mYdbbw==", + "node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.18.0.tgz", + "integrity": "sha512-0UyyRHyDN42QL+NbqevXIIUnKA47A+45WyasO+y2bGJ1mhQrfrtXUpTxCOrfxCR4esV3/RLYyucGVPiUsO8xjg==", "cpu": [ - "arm64" + "s390x" ], "dev": true, "optional": true, "os": [ - "freebsd" - ], - "engines": { - "node": ">=12" - } + "linux" + ] }, - "node_modules/@esbuild/freebsd-x64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.20.2.tgz", - "integrity": "sha512-d+DipyvHRuqEeM5zDivKV1KuXn9WeRX6vqSqIDgwIfPQtwMP4jaDsQsDncjTDDsExT4lR/91OLjRo8bmC1e+Cw==", + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.18.0.tgz", + "integrity": "sha512-xuglR2rBVHA5UsI8h8UbX4VJ470PtGCf5Vpswh7p2ukaqBGFTnsfzxUBetoWBWymHMxbIG0Cmx7Y9qDZzr648w==", "cpu": [ "x64" ], "dev": true, "optional": true, "os": [ - "freebsd" - ], - "engines": { - "node": ">=12" - } + "linux" + ] }, - "node_modules/@esbuild/linux-arm": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.20.2.tgz", - "integrity": "sha512-VhLPeR8HTMPccbuWWcEUD1Az68TqaTYyj6nfE4QByZIQEQVWBB8vup8PpR7y1QHL3CpcF6xd5WVBU/+SBEvGTg==", + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.18.0.tgz", + "integrity": "sha512-LKaqQL9osY/ir2geuLVvRRs+utWUNilzdE90TpyoX0eNqPzWjRm14oMEE+YLve4k/NAqCdPkGYDaDF5Sw+xBfg==", "cpu": [ - "arm" + "x64" ], "dev": true, "optional": true, "os": [ "linux" - ], - "engines": { - "node": ">=12" - } + ] }, - "node_modules/@esbuild/linux-arm64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.20.2.tgz", - "integrity": "sha512-9pb6rBjGvTFNira2FLIWqDk/uaf42sSyLE8j1rnUpuzsODBq7FvpwHYZxQ/It/8b+QOS1RYfqgGFNLRI+qlq2A==", + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.18.0.tgz", + "integrity": "sha512-7J6TkZQFGo9qBKH0pk2cEVSRhJbL6MtfWxth7Y5YmZs57Pi+4x6c2dStAUvaQkHQLnEQv1jzBUW43GvZW8OFqA==", "cpu": [ "arm64" ], "dev": true, "optional": true, "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } + "win32" + ] }, - "node_modules/@esbuild/linux-ia32": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.20.2.tgz", - "integrity": "sha512-o10utieEkNPFDZFQm9CoP7Tvb33UutoJqg3qKf1PWVeeJhJw0Q347PxMvBgVVFgouYLGIhFYG0UGdBumROyiig==", + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.18.0.tgz", + "integrity": "sha512-Txjh+IxBPbkUB9+SXZMpv+b/vnTEtFyfWZgJ6iyCmt2tdx0OF5WhFowLmnh8ENGNpfUlUZkdI//4IEmhwPieNg==", "cpu": [ "ia32" ], "dev": true, "optional": true, "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } + "win32" + ] }, - "node_modules/@esbuild/linux-loong64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.20.2.tgz", - "integrity": "sha512-PR7sp6R/UC4CFVomVINKJ80pMFlfDfMQMYynX7t1tNTeivQ6XdX5r2XovMmha/VjR1YN/HgHWsVcTRIMkymrgQ==", + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.18.0.tgz", + "integrity": "sha512-UOo5FdvOL0+eIVTgS4tIdbW+TtnBLWg1YBCcU2KWM7nuNwRz9bksDX1bekJJCpu25N1DVWaCwnT39dVQxzqS8g==", "cpu": [ - "loong64" + "x64" ], "dev": true, "optional": true, "os": [ - "linux" - ], - "engines": { - "node": ">=12" + "win32" + ] + }, + "node_modules/@rushstack/node-core-library": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/@rushstack/node-core-library/-/node-core-library-5.4.1.tgz", + "integrity": "sha512-WNnwdS8r9NZ/2K3u29tNoSRldscFa7SxU0RT+82B6Dy2I4Hl2MeCSKm4EXLXPKeNzLGvJ1cqbUhTLviSF8E6iA==", + "dev": true, + "dependencies": { + "ajv": "~8.13.0", + "ajv-draft-04": "~1.0.0", + "ajv-formats": "~3.0.1", + "fs-extra": "~7.0.1", + "import-lazy": "~4.0.0", + "jju": "~1.4.0", + "resolve": "~1.22.1", + "semver": "~7.5.4" + }, + "peerDependencies": { + "@types/node": "*" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } } }, - "node_modules/@esbuild/linux-mips64el": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.20.2.tgz", - "integrity": "sha512-4BlTqeutE/KnOiTG5Y6Sb/Hw6hsBOZapOVF6njAESHInhlQAghVVZL1ZpIctBOoTFbQyGW+LsVYZ8lSSB3wkjA==", - "cpu": [ - "mips64el" - ], + "node_modules/@rushstack/node-core-library/node_modules/ajv": { + "version": "8.13.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.13.0.tgz", + "integrity": "sha512-PRA911Blj99jR5RMeTunVbNXMF6Lp4vZXnk5GQjcnUWUTsrXtekg/pnmFFI2u/I36Y/2bITGS30GZCXei6uNkA==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.3", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.4.1" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/@rushstack/node-core-library/node_modules/ajv-draft-04": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/ajv-draft-04/-/ajv-draft-04-1.0.0.tgz", + "integrity": "sha512-mv00Te6nmYbRp5DCwclxtt7yV/joXJPGS7nM+97GdxvuttCOfgI3K4U25zboyeX0O+myI8ERluxQe5wljMmVIw==", + "dev": true, + "peerDependencies": { + "ajv": "^8.5.0" + }, + "peerDependenciesMeta": { + "ajv": { + "optional": true + } + } + }, + "node_modules/@rushstack/node-core-library/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true + }, + "node_modules/@rushstack/rig-package": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/@rushstack/rig-package/-/rig-package-0.5.2.tgz", + "integrity": "sha512-mUDecIJeH3yYGZs2a48k+pbhM6JYwWlgjs2Ca5f2n1G2/kgdgP9D/07oglEGf6mRyXEnazhEENeYTSNDRCwdqA==", + "dev": true, + "dependencies": { + "resolve": "~1.22.1", + "strip-json-comments": "~3.1.1" + } + }, + "node_modules/@rushstack/terminal": { + "version": "0.13.0", + "resolved": "https://registry.npmjs.org/@rushstack/terminal/-/terminal-0.13.0.tgz", + "integrity": "sha512-Ou44Q2s81BqJu3dpYedAX54am9vn245F0HzqVrfJCMQk5pGgoKKOBOjkbfZC9QKcGNaECh6pwH2s5noJt7X6ew==", + "dev": true, + "dependencies": { + "@rushstack/node-core-library": "5.4.1", + "supports-color": "~8.1.1" + }, + "peerDependencies": { + "@types/node": "*" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/@rushstack/ts-command-line": { + "version": "4.22.0", + "resolved": "https://registry.npmjs.org/@rushstack/ts-command-line/-/ts-command-line-4.22.0.tgz", + "integrity": "sha512-Qj28t6MO3HRgAZ72FDeFsrpdE6wBWxF3VENgvrXh7JF2qIT+CrXiOJIesW80VFZB9QwObSpkB1ilx794fGQg6g==", + "dev": true, + "dependencies": { + "@rushstack/terminal": "0.13.0", + "@types/argparse": "1.0.38", + "argparse": "~1.0.9", + "string-argv": "~0.3.1" + } + }, + "node_modules/@swc/core": { + "version": "1.5.25", + "resolved": "https://registry.npmjs.org/@swc/core/-/core-1.5.25.tgz", + "integrity": "sha512-qdGEIdLVoTjEQ7w72UyyQ0wLFY4XbHfZiidmPHKJQsvSXzdpHXxPdlTCea/mY4AhMqo/M+pvkJSXJAxZnFl7qw==", "dev": true, + "hasInstallScript": true, "optional": true, - "os": [ - "linux" - ], + "peer": true, + "dependencies": { + "@swc/counter": "^0.1.3", + "@swc/types": "^0.1.7" + }, "engines": { - "node": ">=12" + "node": ">=10" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/swc" + }, + "optionalDependencies": { + "@swc/core-darwin-arm64": "1.5.25", + "@swc/core-darwin-x64": "1.5.25", + "@swc/core-linux-arm-gnueabihf": "1.5.25", + "@swc/core-linux-arm64-gnu": "1.5.25", + "@swc/core-linux-arm64-musl": "1.5.25", + "@swc/core-linux-x64-gnu": "1.5.25", + "@swc/core-linux-x64-musl": "1.5.25", + "@swc/core-win32-arm64-msvc": "1.5.25", + "@swc/core-win32-ia32-msvc": "1.5.25", + "@swc/core-win32-x64-msvc": "1.5.25" + }, + "peerDependencies": { + "@swc/helpers": "*" + }, + "peerDependenciesMeta": { + "@swc/helpers": { + "optional": true + } } }, - "node_modules/@esbuild/linux-ppc64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.20.2.tgz", - "integrity": "sha512-rD3KsaDprDcfajSKdn25ooz5J5/fWBylaaXkuotBDGnMnDP1Uv5DLAN/45qfnf3JDYyJv/ytGHQaziHUdyzaAg==", + "node_modules/@swc/core-darwin-arm64": { + "version": "1.5.25", + "resolved": "https://registry.npmjs.org/@swc/core-darwin-arm64/-/core-darwin-arm64-1.5.25.tgz", + "integrity": "sha512-YbD0SBgVJS2DM0vwJTU5m7+wOyCjHPBDMf3nCBJQzFZzOLzK11eRW7SzU2jhJHr9HI9sKcNFfN4lIC2Sj+4inA==", "cpu": [ - "ppc64" + "arm64" ], "dev": true, "optional": true, "os": [ - "linux" + "darwin" ], + "peer": true, "engines": { - "node": ">=12" + "node": ">=10" } }, - "node_modules/@esbuild/linux-riscv64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.20.2.tgz", - "integrity": "sha512-snwmBKacKmwTMmhLlz/3aH1Q9T8v45bKYGE3j26TsaOVtjIag4wLfWSiZykXzXuE1kbCE+zJRmwp+ZbIHinnVg==", + "node_modules/@swc/core-darwin-x64": { + "version": "1.5.25", + "resolved": "https://registry.npmjs.org/@swc/core-darwin-x64/-/core-darwin-x64-1.5.25.tgz", + "integrity": "sha512-OhP4TROT6gQuozn+ah0Y4UidSdgDmxwtQq3lgCUIAxJYErJAQ82/Y0kve2UaNmkSGjOHU+/b4siHPrYTkXOk0Q==", "cpu": [ - "riscv64" + "x64" ], "dev": true, "optional": true, "os": [ - "linux" + "darwin" ], + "peer": true, "engines": { - "node": ">=12" + "node": ">=10" } }, - "node_modules/@esbuild/linux-s390x": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.20.2.tgz", - "integrity": "sha512-wcWISOobRWNm3cezm5HOZcYz1sKoHLd8VL1dl309DiixxVFoFe/o8HnwuIwn6sXre88Nwj+VwZUvJf4AFxkyrQ==", + "node_modules/@swc/core-linux-arm-gnueabihf": { + "version": "1.5.25", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.5.25.tgz", + "integrity": "sha512-tNmUfrAHxN2gvYPyYNnHx2CYlPO7DGAUuK/bZrqawu++djcg+atAV3eI3XYJgmHId7/sYAlDQ9wjkrOLofFjVg==", "cpu": [ - "s390x" + "arm" ], "dev": true, "optional": true, "os": [ "linux" ], + "peer": true, "engines": { - "node": ">=12" + "node": ">=10" } }, - "node_modules/@esbuild/linux-x64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.20.2.tgz", - "integrity": "sha512-1MdwI6OOTsfQfek8sLwgyjOXAu+wKhLEoaOLTjbijk6E2WONYpH9ZU2mNtR+lZ2B4uwr+usqGuVfFT9tMtGvGw==", + "node_modules/@swc/core-linux-arm64-gnu": { + "version": "1.5.25", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.5.25.tgz", + "integrity": "sha512-stzpke+bRaNFM/HrZPRjX0aQZ86S/2DChVCwb8NAV1n5lu9mz1CS750y7WbbtX/KZjk92FsCeRy2qwkvjI0gWw==", "cpu": [ - "x64" + "arm64" ], "dev": true, "optional": true, "os": [ "linux" ], + "peer": true, "engines": { - "node": ">=12" + "node": ">=10" } }, - "node_modules/@esbuild/netbsd-x64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.20.2.tgz", - "integrity": "sha512-K8/DhBxcVQkzYc43yJXDSyjlFeHQJBiowJ0uVL6Tor3jGQfSGHNNJcWxNbOI8v5k82prYqzPuwkzHt3J1T1iZQ==", + "node_modules/@swc/core-linux-arm64-musl": { + "version": "1.5.25", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.5.25.tgz", + "integrity": "sha512-UckUfDYedish/bj2V1jgQDGgouLhyRpG7jgF3mp8jHir11V2K6JiTyjFoz99eOiclS3+hNdr4QLJ+ifrQMJNZw==", "cpu": [ - "x64" + "arm64" ], "dev": true, "optional": true, "os": [ - "netbsd" + "linux" ], + "peer": true, "engines": { - "node": ">=12" + "node": ">=10" } }, - "node_modules/@esbuild/openbsd-x64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.20.2.tgz", - "integrity": "sha512-eMpKlV0SThJmmJgiVyN9jTPJ2VBPquf6Kt/nAoo6DgHAoN57K15ZghiHaMvqjCye/uU4X5u3YSMgVBI1h3vKrQ==", + "node_modules/@swc/core-linux-x64-gnu": { + "version": "1.5.25", + "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.5.25.tgz", + "integrity": "sha512-LwbJEgNT3lXbvz4WFzVNXNvs8DvxpoXjMZk9K9Hig8tmZQJKHC2qZTGomcyK5EFzfj2HBuBXZnAEW8ZT9PcEaA==", "cpu": [ "x64" ], "dev": true, "optional": true, "os": [ - "openbsd" + "linux" ], + "peer": true, "engines": { - "node": ">=12" + "node": ">=10" } }, - "node_modules/@esbuild/sunos-x64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.20.2.tgz", - "integrity": "sha512-2UyFtRC6cXLyejf/YEld4Hajo7UHILetzE1vsRcGL3earZEW77JxrFjH4Ez2qaTiEfMgAXxfAZCm1fvM/G/o8w==", + "node_modules/@swc/core-linux-x64-musl": { + "version": "1.5.25", + "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.5.25.tgz", + "integrity": "sha512-rsepMTgml0EkswWkBpg3Wrjj5eqjwTzZN5omAn1klzXSZnClTrfeHvBuoIJYVr1yx+jmBkqySgME2p7+magUAw==", "cpu": [ "x64" ], "dev": true, "optional": true, "os": [ - "sunos" + "linux" ], + "peer": true, "engines": { - "node": ">=12" + "node": ">=10" } }, - "node_modules/@esbuild/win32-arm64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.20.2.tgz", - "integrity": "sha512-GRibxoawM9ZCnDxnP3usoUDO9vUkpAxIIZ6GQI+IlVmr5kP3zUq+l17xELTHMWTWzjxa2guPNyrpq1GWmPvcGQ==", + "node_modules/@swc/core-win32-arm64-msvc": { + "version": "1.5.25", + "resolved": "https://registry.npmjs.org/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.5.25.tgz", + "integrity": "sha512-DJDsLBsRBV3uQBShRK2x6fqzABp9RLNVxDUpTTvUjc7qywJ8vS/yn+POK/zCyVEqLagf1z/8D5CEQ+RAIJq1NA==", "cpu": [ "arm64" ], @@ -2087,247 +1315,89 @@ "os": [ "win32" ], + "peer": true, "engines": { - "node": ">=12" + "node": ">=10" } }, - "node_modules/@esbuild/win32-ia32": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.20.2.tgz", - "integrity": "sha512-HfLOfn9YWmkSKRQqovpnITazdtquEW8/SoHW7pWpuEeguaZI4QnCRW6b+oZTztdBnZOS2hqJ6im/D5cPzBTTlQ==", + "node_modules/@swc/core-win32-ia32-msvc": { + "version": "1.5.25", + "resolved": "https://registry.npmjs.org/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.5.25.tgz", + "integrity": "sha512-BARL1ulHol53MEKC1ZVWM3A3FP757UUgG5Q8v97za+4a1SaIgbwvAQyHDxMYWi9+ij+OapK8YnWjJcFa17g8dw==", "cpu": [ "ia32" ], "dev": true, "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/win32-x64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.20.2.tgz", - "integrity": "sha512-N49X4lJX27+l9jbLKSqZ6bKNjzQvHaT8IIFUy+YIqmXQdjYCToGWwOItDrfby14c78aDd5NHQl29xingXfCdLQ==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@eslint-community/eslint-utils": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", - "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", - "dev": true, - "dependencies": { - "eslint-visitor-keys": "^3.3.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" - } - }, - "node_modules/@eslint-community/regexpp": { - "version": "4.10.0", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.10.0.tgz", - "integrity": "sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==", - "dev": true, - "engines": { - "node": "^12.0.0 || ^14.0.0 || >=16.0.0" - } - }, - "node_modules/@eslint/eslintrc": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", - "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", - "dev": true, - "dependencies": { - "ajv": "^6.12.4", - "debug": "^4.3.2", - "espree": "^9.6.0", - "globals": "^13.19.0", - "ignore": "^5.2.0", - "import-fresh": "^3.2.1", - "js-yaml": "^4.1.0", - "minimatch": "^3.1.2", - "strip-json-comments": "^3.1.1" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/@eslint/eslintrc/node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true - }, - "node_modules/@eslint/eslintrc/node_modules/globals": { - "version": "13.24.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", - "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", - "dev": true, - "dependencies": { - "type-fest": "^0.20.2" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@eslint/eslintrc/node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dev": true, - "dependencies": { - "argparse": "^2.0.1" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/@eslint/js": { - "version": "8.57.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.0.tgz", - "integrity": "sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==", - "dev": true, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - } - }, - "node_modules/@humanwhocodes/config-array": { - "version": "0.11.14", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz", - "integrity": "sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==", - "dev": true, - "dependencies": { - "@humanwhocodes/object-schema": "^2.0.2", - "debug": "^4.3.1", - "minimatch": "^3.0.5" - }, - "engines": { - "node": ">=10.10.0" - } - }, - "node_modules/@humanwhocodes/module-importer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", - "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", - "dev": true, - "engines": { - "node": ">=12.22" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/nzakas" - } - }, - "node_modules/@humanwhocodes/object-schema": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz", - "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", - "dev": true - }, - "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", - "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", - "dev": true, - "dependencies": { - "@jridgewell/set-array": "^1.2.1", - "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.24" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", - "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", - "dev": true, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/set-array": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", - "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", - "dev": true, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.4.15", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", - "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", - "dev": true - }, - "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.25", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", - "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", - "dev": true, - "dependencies": { - "@jridgewell/resolve-uri": "^3.1.0", - "@jridgewell/sourcemap-codec": "^1.4.14" + "os": [ + "win32" + ], + "peer": true, + "engines": { + "node": ">=10" } }, - "node_modules/@nodelib/fs.scandir": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", - "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "node_modules/@swc/core-win32-x64-msvc": { + "version": "1.5.25", + "resolved": "https://registry.npmjs.org/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.5.25.tgz", + "integrity": "sha512-o+MHUWrQI9iR6EusEV8eNU2Ezi3KtlhUR4gfptQN5MbVzlgjTvQbhiKpE1GYOxp+0BLBbKRwITKOcdhxfEJ2Uw==", + "cpu": [ + "x64" + ], "dev": true, - "dependencies": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" - }, + "optional": true, + "os": [ + "win32" + ], + "peer": true, "engines": { - "node": ">= 8" + "node": ">=10" } }, - "node_modules/@nodelib/fs.stat": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", - "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "node_modules/@swc/counter": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@swc/counter/-/counter-0.1.3.tgz", + "integrity": "sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==", "dev": true, - "engines": { - "node": ">= 8" + "optional": true, + "peer": true + }, + "node_modules/@swc/helpers": { + "version": "0.5.11", + "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.11.tgz", + "integrity": "sha512-YNlnKRWF2sVojTpIyzwou9XoTNbzbzONwRhOoniEioF1AtaitTvVZblaQRrAzChWQ1bLYyYSWzM18y4WwgzJ+A==", + "dependencies": { + "tslib": "^2.4.0" } }, - "node_modules/@nodelib/fs.walk": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", - "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "node_modules/@swc/helpers/node_modules/tslib": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.3.tgz", + "integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==" + }, + "node_modules/@swc/types": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/@swc/types/-/types-0.1.7.tgz", + "integrity": "sha512-scHWahbHF0eyj3JsxG9CFJgFdFNaVQCNAimBlT6PzS3n/HptxqREjsm4OH6AN3lYcffZYSPxXW8ua2BEHp0lJQ==", "dev": true, + "optional": true, + "peer": true, "dependencies": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" - }, - "engines": { - "node": ">= 8" + "@swc/counter": "^0.1.3" } }, + "node_modules/@types/argparse": { + "version": "1.0.38", + "resolved": "https://registry.npmjs.org/@types/argparse/-/argparse-1.0.38.tgz", + "integrity": "sha512-ebDJ9b0e702Yr7pWgB0jzm+CX4Srzz8RcXtLJDJB+BSccqMa36uyH/zUsSYao5+BD1ytv3k3rPYCq4mAE1hsXA==", + "dev": true + }, + "node_modules/@types/estree": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", + "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==", + "dev": true + }, "node_modules/@types/json-schema": { "version": "7.0.15", "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", @@ -2338,7 +1408,6 @@ "version": "20.12.7", "resolved": "https://registry.npmjs.org/@types/node/-/node-20.12.7.tgz", "integrity": "sha512-wq0cICSkRLVaf3UGLMGItu/PtdY7oaXaI/RVU+xliKVOtRna3PRY57ZDfztpDL0n11vfymMUnXv8QwYCO7L1wg==", - "dev": true, "dependencies": { "undici-types": "~5.26.4" } @@ -2352,14 +1421,12 @@ "node_modules/@types/uuid": { "version": "8.3.4", "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-8.3.4.tgz", - "integrity": "sha512-c/I8ZRb51j+pYGAu5CrFMRxqZ2ke4y2grEBO5AUjgSkSk+qT2Ea+OdWElz/OiMf5MNpn2b17kuVBwZLQJXzihw==", - "dev": true + "integrity": "sha512-c/I8ZRb51j+pYGAu5CrFMRxqZ2ke4y2grEBO5AUjgSkSk+qT2Ea+OdWElz/OiMf5MNpn2b17kuVBwZLQJXzihw==" }, "node_modules/@types/ws": { "version": "8.5.10", "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.10.tgz", "integrity": "sha512-vmQSUcfalpIq0R9q7uTo2lXs6eGIpt9wtnLdMv9LVpIjCA/+ufZRozlVoVelIYixx1ugCBKDhn89vnsEGOCx9A==", - "dev": true, "dependencies": { "@types/node": "*" } @@ -2398,18 +1465,6 @@ } } }, - "node_modules/@typescript-eslint/eslint-plugin/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/semver": { "version": "7.6.0", "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", @@ -2425,12 +1480,6 @@ "node": ">=10" } }, - "node_modules/@typescript-eslint/eslint-plugin/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - }, "node_modules/@typescript-eslint/parser": { "version": "5.62.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.62.0.tgz", @@ -2542,18 +1591,6 @@ } } }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/@typescript-eslint/typescript-estree/node_modules/semver": { "version": "7.6.0", "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", @@ -2569,12 +1606,6 @@ "node": ">=10" } }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - }, "node_modules/@typescript-eslint/utils": { "version": "5.62.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.62.0.tgz", @@ -2601,18 +1632,6 @@ "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, - "node_modules/@typescript-eslint/utils/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/@typescript-eslint/utils/node_modules/semver": { "version": "7.6.0", "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", @@ -2628,12 +1647,6 @@ "node": ">=10" } }, - "node_modules/@typescript-eslint/utils/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - }, "node_modules/@typescript-eslint/visitor-keys": { "version": "5.62.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.62.0.tgz", @@ -2700,6 +1713,45 @@ "url": "https://github.com/sponsors/epoberezkin" } }, + "node_modules/ajv-formats": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-3.0.1.tgz", + "integrity": "sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ==", + "dev": true, + "dependencies": { + "ajv": "^8.0.0" + }, + "peerDependencies": { + "ajv": "^8.0.0" + }, + "peerDependenciesMeta": { + "ajv": { + "optional": true + } + } + }, + "node_modules/ajv-formats/node_modules/ajv": { + "version": "8.16.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.16.0.tgz", + "integrity": "sha512-F0twR8U1ZU67JIEtekUcLkXkoO5mMMmgGD8sK/xUFzJ805jxHQl92hImFAqqXMyMYjSPOyUPAwHYhB72g5sTXw==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.3", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.4.1" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ajv-formats/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true + }, "node_modules/amdefine": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", @@ -2728,17 +1780,11 @@ "node": ">=8" } }, - "node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "dependencies": { - "color-convert": "^1.9.0" - }, - "engines": { - "node": ">=4" - } + "node_modules/any-promise": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", + "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==", + "dev": true }, "node_modules/anymatch": { "version": "3.1.3", @@ -2825,81 +1871,31 @@ "integrity": "sha512-NmWvPnx0F1SfrQbYwOi7OeaNGokp9XhzNioJ/CSBs8Qa4vxug81mhJEAVZwxXuBmYB5KDRfMq/F3RR0BIU7sWg==", "dev": true }, - "node_modules/babel-eslint": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/babel-eslint/-/babel-eslint-10.1.0.tgz", - "integrity": "sha512-ifWaTHQ0ce+448CYop8AdrQiBsGrnC+bMgfyKFdi6EsPLTAWG+QfyDeM6OH+FmWnKvEq5NnBMLvlBUPKQZoDSg==", - "deprecated": "babel-eslint is now @babel/eslint-parser. This package will no longer receive updates.", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.0.0", - "@babel/parser": "^7.7.0", - "@babel/traverse": "^7.7.0", - "@babel/types": "^7.7.0", - "eslint-visitor-keys": "^1.0.0", - "resolve": "^1.12.0" - }, - "engines": { - "node": ">=6" - }, - "peerDependencies": { - "eslint": ">= 4.12.1" - } - }, - "node_modules/babel-eslint/node_modules/eslint-visitor-keys": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", - "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/babel-plugin-polyfill-corejs2": { - "version": "0.4.10", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.10.tgz", - "integrity": "sha512-rpIuu//y5OX6jVU+a5BCn1R5RSZYWAl2Nar76iwaOdycqb6JPxediskWFMMl7stfwNJR4b7eiQvh5fB5TEQJTQ==", - "dev": true, - "dependencies": { - "@babel/compat-data": "^7.22.6", - "@babel/helper-define-polyfill-provider": "^0.6.1", - "semver": "^6.3.1" - }, - "peerDependencies": { - "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" - } - }, - "node_modules/babel-plugin-polyfill-corejs3": { - "version": "0.10.4", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.10.4.tgz", - "integrity": "sha512-25J6I8NGfa5YkCDogHRID3fVCadIR8/pGl1/spvCkzb6lVn6SR3ojpx9nOn9iEBcUsjY24AmdKm5khcfKdylcg==", - "dev": true, - "dependencies": { - "@babel/helper-define-polyfill-provider": "^0.6.1", - "core-js-compat": "^3.36.1" - }, - "peerDependencies": { - "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" - } - }, - "node_modules/babel-plugin-polyfill-regenerator": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.1.tgz", - "integrity": "sha512-JfTApdE++cgcTWjsiCQlLyFBMbTUft9ja17saCc93lgV33h4tuCVj7tlvu//qpLwaG+3yEz7/KhahGrUMkVq9g==", - "dev": true, - "dependencies": { - "@babel/helper-define-polyfill-provider": "^0.6.1" - }, - "peerDependencies": { - "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" - } - }, "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", "dev": true }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, "node_modules/bcrypt-pbkdf": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", @@ -2949,36 +1945,27 @@ "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", "dev": true }, - "node_modules/browserslist": { - "version": "4.23.0", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.0.tgz", - "integrity": "sha512-QW8HiM1shhT2GuzkvklfjcKDiWFXHOeFCIA/huJPwHsslwcydgk7X+z2zXpEijP98UCY7HbubZt5J2Zgvf0CaQ==", - "dev": true, + "node_modules/buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", "funding": [ { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" + "type": "github", + "url": "https://github.com/sponsors/feross" }, { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" + "type": "patreon", + "url": "https://www.patreon.com/feross" }, { - "type": "github", - "url": "https://github.com/sponsors/ai" + "type": "consulting", + "url": "https://feross.org/support" } ], "dependencies": { - "caniuse-lite": "^1.0.30001587", - "electron-to-chromium": "^1.4.668", - "node-releases": "^2.0.14", - "update-browserslist-db": "^1.0.13" - }, - "bin": { - "browserslist": "cli.js" - }, - "engines": { - "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" } }, "node_modules/bufferutil": { @@ -2994,6 +1981,49 @@ "node": ">=6.14.2" } }, + "node_modules/bundle-require": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/bundle-require/-/bundle-require-4.2.1.tgz", + "integrity": "sha512-7Q/6vkyYAwOmQNRw75x+4yRtZCZJXUDmHHlFdkiV0wgv/reNjtJwpu1jPJ0w2kbEpIM0uoKI3S4/f39dU7AjSA==", + "dev": true, + "dependencies": { + "load-tsconfig": "^0.2.3" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "peerDependencies": { + "esbuild": ">=0.17" + } + }, + "node_modules/cac": { + "version": "6.7.14", + "resolved": "https://registry.npmjs.org/cac/-/cac-6.7.14.tgz", + "integrity": "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/call-bind": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", + "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", + "dev": true, + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "set-function-length": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/callsites": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", @@ -3015,26 +2045,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/caniuse-lite": { - "version": "1.0.30001609", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001609.tgz", - "integrity": "sha512-JFPQs34lHKx1B5t1EpQpWH4c+29zIyn/haGsbpfq3suuV9v56enjFt23zqijxGTMwy1p/4H2tjnQMY+p1WoAyA==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/caniuse-lite" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ] - }, "node_modules/caseless": { "version": "0.12.0", "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", @@ -3059,20 +2069,6 @@ "node": ">=4" } }, - "node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/check-error": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.3.tgz", @@ -3085,6 +2081,30 @@ "node": "*" } }, + "node_modules/chokidar": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "dev": true, + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, "node_modules/cliui": { "version": "7.0.4", "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", @@ -3096,21 +2116,6 @@ "wrap-ansi": "^7.0.0" } }, - "node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "dependencies": { - "color-name": "1.1.3" - } - }, - "node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", - "dev": true - }, "node_modules/combined-stream": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", @@ -3129,25 +2134,6 @@ "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", "dev": true }, - "node_modules/convert-source-map": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", - "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", - "dev": true - }, - "node_modules/core-js-compat": { - "version": "3.36.1", - "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.36.1.tgz", - "integrity": "sha512-Dk997v9ZCt3X/npqzyGdTlq6t7lDBhZwGvV94PKzDArjp7BTRm7WlDAXYd/OWdeFHO8OChQYRJNJvUCqCbrtKA==", - "dev": true, - "dependencies": { - "browserslist": "^4.23.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/core-js" - } - }, "node_modules/coveralls": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/coveralls/-/coveralls-3.1.1.tgz", @@ -3240,6 +2226,23 @@ "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", "dev": true }, + "node_modules/define-data-property": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "dev": true, + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/delayed-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", @@ -3282,6 +2285,12 @@ "node": ">=6.0.0" } }, + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "dev": true + }, "node_modules/ecc-jsbn": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", @@ -3292,22 +2301,37 @@ "safer-buffer": "^2.1.0" } }, - "node_modules/electron-to-chromium": { - "version": "1.4.736", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.736.tgz", - "integrity": "sha512-Rer6wc3ynLelKNM4lOCg7/zPQj8tPOCB2hzD32PX9wd3hgRRi9MxEbmkFCokzcEhRVMiOVLjnL9ig9cefJ+6+Q==", - "dev": true - }, "node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", "dev": true }, + "node_modules/es-define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", + "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.2.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/esbuild": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.20.2.tgz", - "integrity": "sha512-WdOOppmUNU+IbZ0PaDiTst80zjnrOkyJNHoKupIcVyU8Lvla3Ugx94VzkQ32Ijqd7UhHJy75gNWDMUekcrSJ6g==", + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz", + "integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==", "dev": true, "hasInstallScript": true, "bin": { @@ -3317,38 +2341,42 @@ "node": ">=12" }, "optionalDependencies": { - "@esbuild/aix-ppc64": "0.20.2", - "@esbuild/android-arm": "0.20.2", - "@esbuild/android-arm64": "0.20.2", - "@esbuild/android-x64": "0.20.2", - "@esbuild/darwin-arm64": "0.20.2", - "@esbuild/darwin-x64": "0.20.2", - "@esbuild/freebsd-arm64": "0.20.2", - "@esbuild/freebsd-x64": "0.20.2", - "@esbuild/linux-arm": "0.20.2", - "@esbuild/linux-arm64": "0.20.2", - "@esbuild/linux-ia32": "0.20.2", - "@esbuild/linux-loong64": "0.20.2", - "@esbuild/linux-mips64el": "0.20.2", - "@esbuild/linux-ppc64": "0.20.2", - "@esbuild/linux-riscv64": "0.20.2", - "@esbuild/linux-s390x": "0.20.2", - "@esbuild/linux-x64": "0.20.2", - "@esbuild/netbsd-x64": "0.20.2", - "@esbuild/openbsd-x64": "0.20.2", - "@esbuild/sunos-x64": "0.20.2", - "@esbuild/win32-arm64": "0.20.2", - "@esbuild/win32-ia32": "0.20.2", - "@esbuild/win32-x64": "0.20.2" - } - }, - "node_modules/esbuild-plugin-babel": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/esbuild-plugin-babel/-/esbuild-plugin-babel-0.2.3.tgz", - "integrity": "sha512-hGLL31n+GvBhkHUpPCt1sU4ynzOH7I1IUkKhera66jigi4mHFPL6dfJo44L6/1rfcZudXx+wGdf9VOifzDPqYQ==", + "@esbuild/aix-ppc64": "0.21.5", + "@esbuild/android-arm": "0.21.5", + "@esbuild/android-arm64": "0.21.5", + "@esbuild/android-x64": "0.21.5", + "@esbuild/darwin-arm64": "0.21.5", + "@esbuild/darwin-x64": "0.21.5", + "@esbuild/freebsd-arm64": "0.21.5", + "@esbuild/freebsd-x64": "0.21.5", + "@esbuild/linux-arm": "0.21.5", + "@esbuild/linux-arm64": "0.21.5", + "@esbuild/linux-ia32": "0.21.5", + "@esbuild/linux-loong64": "0.21.5", + "@esbuild/linux-mips64el": "0.21.5", + "@esbuild/linux-ppc64": "0.21.5", + "@esbuild/linux-riscv64": "0.21.5", + "@esbuild/linux-s390x": "0.21.5", + "@esbuild/linux-x64": "0.21.5", + "@esbuild/netbsd-x64": "0.21.5", + "@esbuild/openbsd-x64": "0.21.5", + "@esbuild/sunos-x64": "0.21.5", + "@esbuild/win32-arm64": "0.21.5", + "@esbuild/win32-ia32": "0.21.5", + "@esbuild/win32-x64": "0.21.5" + } + }, + "node_modules/esbuild-plugin-polyfill-node": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/esbuild-plugin-polyfill-node/-/esbuild-plugin-polyfill-node-0.3.0.tgz", + "integrity": "sha512-SHG6CKUfWfYyYXGpW143NEZtcVVn8S/WHcEOxk62LuDXnY4Zpmc+WmxJKN6GMTgTClXJXhEM5KQlxKY6YjbucQ==", "dev": true, + "dependencies": { + "@jspm/core": "^2.0.1", + "import-meta-resolve": "^3.0.0" + }, "peerDependencies": { - "@babel/core": "^7.0.0" + "esbuild": "*" } }, "node_modules/escalade": { @@ -3360,15 +2388,6 @@ "node": ">=6" } }, - "node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "dev": true, - "engines": { - "node": ">=0.8.0" - } - }, "node_modules/escodegen": { "version": "1.8.1", "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.8.1.tgz", @@ -3663,15 +2682,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/eslint/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, "node_modules/eslint/node_modules/js-yaml": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", @@ -3791,6 +2801,29 @@ "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==" }, + "node_modules/execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, "node_modules/extend": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", @@ -3918,6 +2951,34 @@ "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==", "dev": true }, + "node_modules/foreground-child": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.1.1.tgz", + "integrity": "sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.0", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/foreground-child/node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/forever-agent": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", @@ -3941,6 +3002,20 @@ "node": ">= 0.12" } }, + "node_modules/fs-extra": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz", + "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.2", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + }, + "engines": { + "node": ">=6 <7 || >=8" + } + }, "node_modules/fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", @@ -3970,15 +3045,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/gensync": { - "version": "1.0.0-beta.2", - "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", - "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, "node_modules/get-caller-file": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", @@ -3997,6 +3063,37 @@ "node": "*" } }, + "node_modules/get-intrinsic": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", + "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", + "dev": true, + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "hasown": "^2.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/getpass": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", @@ -4038,15 +3135,6 @@ "node": ">= 6" } }, - "node_modules/globals": { - "version": "11.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", - "dev": true, - "engines": { - "node": ">=4" - } - }, "node_modules/globby": { "version": "11.1.0", "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", @@ -4076,6 +3164,24 @@ "node": ">=8" } }, + "node_modules/gopd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", + "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.1.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true + }, "node_modules/graphemer": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", @@ -4103,15 +3209,6 @@ "uglify-js": "^3.1.4" } }, - "node_modules/handlebars/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/har-schema": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", @@ -4136,12 +3233,48 @@ } }, "node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true, "engines": { - "node": ">=4" + "node": ">=8" + } + }, + "node_modules/has-property-descriptors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", + "dev": true, + "dependencies": { + "es-define-property": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-proto": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", + "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/hasown": { @@ -4180,6 +3313,34 @@ "npm": ">=1.3.7" } }, + "node_modules/human-signals": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", + "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", + "dev": true, + "engines": { + "node": ">=10.17.0" + } + }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, "node_modules/ignore": { "version": "5.3.1", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz", @@ -4205,6 +3366,25 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/import-lazy": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-4.0.0.tgz", + "integrity": "sha512-rKtvo6a868b5Hu3heneU+L4yEQ4jYKLtjpnPeUdK7h0yzXGmyBTypknlkCvHFBqfX9YlorEiMM6Dnq/5atfHkw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/import-meta-resolve": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/import-meta-resolve/-/import-meta-resolve-3.1.1.tgz", + "integrity": "sha512-qeywsE/KC3w9Fd2ORrRDUw6nS/nLwZpXgfrOc2IILvZYnCaEMd+D56Vfg9k4G29gIeVi3XKql1RQatME8iYsiw==", + "dev": true, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/imurmurhash": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", @@ -4311,6 +3491,18 @@ "node": ">=8" } }, + "node_modules/is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/is-typedarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", @@ -4428,12 +3620,39 @@ "which": "bin/which" } }, - "node_modules/js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "node_modules/jackspeak": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.0.tgz", + "integrity": "sha512-JVYhQnN59LVPFCEcVa2C3CrEKYacvjRfqIQl+h8oi91aLYQVWRYbxjPcv1bUiUy/kLmQaANrYfNMCO3kuEDHfw==", + "dev": true, + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" + } + }, + "node_modules/jju": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/jju/-/jju-1.4.0.tgz", + "integrity": "sha512-8wb9Yw966OSxApiCt0K3yNJL8pnNeIv+OEq2YMidz4FKP6nonSRoOXc80iXY4JaN2FC11B9qsNmDsm+ZOfMROA==", "dev": true }, + "node_modules/joycon": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/joycon/-/joycon-3.1.1.tgz", + "integrity": "sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw==", + "dev": true, + "engines": { + "node": ">=10" + } + }, "node_modules/js-yaml": { "version": "3.14.1", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", @@ -4466,18 +3685,6 @@ "integrity": "sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==", "dev": true }, - "node_modules/jsesc": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", - "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", - "dev": true, - "bin": { - "jsesc": "bin/jsesc" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/json-buffer": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", @@ -4508,16 +3715,13 @@ "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==", "dev": true }, - "node_modules/json5": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", - "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", - "dev": true, - "bin": { - "json5": "lib/cli.js" - }, - "engines": { - "node": ">=6" + "node_modules/jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", + "dev": true, + "optionalDependencies": { + "graceful-fs": "^4.1.6" } }, "node_modules/jsprim": { @@ -4566,6 +3770,33 @@ "node": ">= 0.8.0" } }, + "node_modules/lilconfig": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.2.tgz", + "integrity": "sha512-eop+wDAvpItUys0FWkHIKeC9ybYrTGbU41U5K7+bttZZeohvnY7M9dZ5kB21GNWiFT2q1OoPTvncPCgSOVO5ow==", + "dev": true, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/antonk52" + } + }, + "node_modules/lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "dev": true + }, + "node_modules/load-tsconfig": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/load-tsconfig/-/load-tsconfig-0.2.5.tgz", + "integrity": "sha512-IXO6OCs9yg8tMKzfPZ1YmheJbZCiEsnBdcB03l0OcfK9prKnJb96siuHCr5Fl37/yo9DnKU+TLpxzTUspw9shg==", + "dev": true, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + } + }, "node_modules/locate-path": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", @@ -4581,10 +3812,10 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/lodash.debounce": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", - "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==", + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", "dev": true }, "node_modules/lodash.merge": { @@ -4593,6 +3824,12 @@ "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", "dev": true }, + "node_modules/lodash.sortby": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz", + "integrity": "sha512-HDWXG8isMntAyRF5vZ7xKuEvOhT4AhlRt/3czTSjvGUxjYCBVRQY48ViDHyfYz9VIoBkW4TMGQNapx+l3RUwdA==", + "dev": true + }, "node_modules/log-driver": { "version": "1.2.7", "resolved": "https://registry.npmjs.org/log-driver/-/log-driver-1.2.7.tgz", @@ -4667,15 +3904,6 @@ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, - "node_modules/log-symbols/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, "node_modules/log-symbols/node_modules/supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", @@ -4698,14 +3926,23 @@ } }, "node_modules/lru-cache": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", - "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", "dev": true, "dependencies": { - "yallist": "^3.0.2" + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" } }, + "node_modules/merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true + }, "node_modules/merge2": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", @@ -4749,6 +3986,15 @@ "node": ">= 0.6" } }, + "node_modules/mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, "node_modules/minimatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", @@ -4770,6 +4016,15 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/minipass": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "dev": true, + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, "node_modules/mkdirp": { "version": "0.5.6", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", @@ -4899,15 +4154,6 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/mocha/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, "node_modules/mocha/node_modules/js-yaml": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", @@ -4938,27 +4184,23 @@ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", "dev": true }, - "node_modules/mocha/node_modules/supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" - } - }, "node_modules/ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "dev": true }, + "node_modules/mz": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", + "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==", + "dev": true, + "dependencies": { + "any-promise": "^1.0.0", + "object-assign": "^4.0.1", + "thenify-all": "^1.0.0" + } + }, "node_modules/natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", @@ -4988,12 +4230,6 @@ "node-gyp-build-test": "build-test.js" } }, - "node_modules/node-releases": { - "version": "2.0.14", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz", - "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==", - "dev": true - }, "node_modules/nopt": { "version": "3.0.6", "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", @@ -5015,6 +4251,18 @@ "node": ">=0.10.0" } }, + "node_modules/npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "dev": true, + "dependencies": { + "path-key": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/oauth-sign": { "version": "0.9.0", "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", @@ -5024,6 +4272,24 @@ "node": "*" } }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-inspect": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz", + "integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", @@ -5033,6 +4299,21 @@ "wrappy": "1" } }, + "node_modules/onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dev": true, + "dependencies": { + "mimic-fn": "^2.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/optionator": { "version": "0.9.3", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz", @@ -5125,6 +4406,31 @@ "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", "dev": true }, + "node_modules/path-scurry": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", + "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", + "dev": true, + "dependencies": { + "lru-cache": "^10.2.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, + "engines": { + "node": ">=16 || 14 >=14.18" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/path-scurry/node_modules/lru-cache": { + "version": "10.2.2", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.2.2.tgz", + "integrity": "sha512-9hp3Vp2/hFQUiIwKo8XCeFVnrg8Pk3TYNPIR7tJADKi5YfcF7vEaK7avFHTlSy3kOKYaJQaalfEo6YuXdceBOQ==", + "dev": true, + "engines": { + "node": "14 || >=16.14" + } + }, "node_modules/path-type": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", @@ -5149,12 +4455,6 @@ "integrity": "sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==", "dev": true }, - "node_modules/picocolors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", - "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", - "dev": true - }, "node_modules/picomatch": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", @@ -5167,6 +4467,50 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, + "node_modules/pirates": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz", + "integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, + "node_modules/postcss-load-config": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-4.0.2.tgz", + "integrity": "sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "lilconfig": "^3.0.0", + "yaml": "^2.3.4" + }, + "engines": { + "node": ">= 14" + }, + "peerDependencies": { + "postcss": ">=8.0.9", + "ts-node": ">=9.0.0" + }, + "peerDependenciesMeta": { + "postcss": { + "optional": true + }, + "ts-node": { + "optional": true + } + } + }, "node_modules/prelude-ls": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", @@ -5182,6 +4526,12 @@ "integrity": "sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==", "dev": true }, + "node_modules/punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ==", + "dev": true + }, "node_modules/qs": { "version": "6.5.3", "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.3.tgz", @@ -5232,77 +4582,6 @@ "node": ">=8.10.0" } }, - "node_modules/regenerate": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", - "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==", - "dev": true - }, - "node_modules/regenerate-unicode-properties": { - "version": "10.1.1", - "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.1.1.tgz", - "integrity": "sha512-X007RyZLsCJVVrjgEFVpLUTZwyOZk3oiL75ZcuYjlIWd6rNJtOjkBwQc5AsRrpbKVkxN6sklw/k/9m2jJYOf8Q==", - "dev": true, - "dependencies": { - "regenerate": "^1.4.2" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/regenerator-runtime": { - "version": "0.14.1", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", - "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==", - "dev": true - }, - "node_modules/regenerator-transform": { - "version": "0.15.2", - "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.15.2.tgz", - "integrity": "sha512-hfMp2BoF0qOk3uc5V20ALGDS2ddjQaLrdl7xrGXvAIow7qeWRM2VA2HuCHkUKk9slq3VwEwLNK3DFBqDfPGYtg==", - "dev": true, - "dependencies": { - "@babel/runtime": "^7.8.4" - } - }, - "node_modules/regexpu-core": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-5.3.2.tgz", - "integrity": "sha512-RAM5FlZz+Lhmo7db9L298p2vHP5ZywrVXmVXpmAD9GuL5MPH6t9ROw1iA/wfHkQ76Qe7AaPF0nGuim96/IrQMQ==", - "dev": true, - "dependencies": { - "@babel/regjsgen": "^0.8.0", - "regenerate": "^1.4.2", - "regenerate-unicode-properties": "^10.1.0", - "regjsparser": "^0.9.1", - "unicode-match-property-ecmascript": "^2.0.0", - "unicode-match-property-value-ecmascript": "^2.1.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/regjsparser": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.9.1.tgz", - "integrity": "sha512-dQUtn90WanSNl+7mQKcXAgZxvUe7Z0SqXlgzv0za4LwiUhyzBC58yQO3liFoUgu8GiJVInAhJjkj1N0EtQ5nkQ==", - "dev": true, - "dependencies": { - "jsesc": "~0.5.0" - }, - "bin": { - "regjsparser": "bin/parser" - } - }, - "node_modules/regjsparser/node_modules/jsesc": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", - "integrity": "sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==", - "dev": true, - "bin": { - "jsesc": "bin/jsesc" - } - }, "node_modules/request": { "version": "2.88.2", "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", @@ -5354,6 +4633,15 @@ "node": ">=0.10.0" } }, + "node_modules/require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/resolve": { "version": "1.22.8", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", @@ -5405,6 +4693,41 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/rollup": { + "version": "4.18.0", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.18.0.tgz", + "integrity": "sha512-QmJz14PX3rzbJCN1SG4Xe/bAAX2a6NpCP8ab2vfu2GiUr8AQcr2nCV/oEO3yneFarB67zk8ShlIyWb2LGTb3Sg==", + "dev": true, + "dependencies": { + "@types/estree": "1.0.5" + }, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.18.0", + "@rollup/rollup-android-arm64": "4.18.0", + "@rollup/rollup-darwin-arm64": "4.18.0", + "@rollup/rollup-darwin-x64": "4.18.0", + "@rollup/rollup-linux-arm-gnueabihf": "4.18.0", + "@rollup/rollup-linux-arm-musleabihf": "4.18.0", + "@rollup/rollup-linux-arm64-gnu": "4.18.0", + "@rollup/rollup-linux-arm64-musl": "4.18.0", + "@rollup/rollup-linux-powerpc64le-gnu": "4.18.0", + "@rollup/rollup-linux-riscv64-gnu": "4.18.0", + "@rollup/rollup-linux-s390x-gnu": "4.18.0", + "@rollup/rollup-linux-x64-gnu": "4.18.0", + "@rollup/rollup-linux-x64-musl": "4.18.0", + "@rollup/rollup-win32-arm64-msvc": "4.18.0", + "@rollup/rollup-win32-ia32-msvc": "4.18.0", + "@rollup/rollup-win32-x64-msvc": "4.18.0", + "fsevents": "~2.3.2" + } + }, "node_modules/run-parallel": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", @@ -5455,12 +4778,18 @@ "dev": true }, "node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, "bin": { "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" } }, "node_modules/serialize-javascript": { @@ -5472,6 +4801,23 @@ "randombytes": "^2.1.0" } }, + "node_modules/set-function-length": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", + "dev": true, + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", @@ -5493,6 +4839,39 @@ "node": ">=8" } }, + "node_modules/side-channel": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", + "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4", + "object-inspect": "^1.13.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "dev": true + }, + "node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/sprintf-js": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", @@ -5524,7 +4903,31 @@ "node": ">=0.10.0" } }, - "node_modules/string-width": { + "node_modules/string-argv": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/string-argv/-/string-argv-0.3.2.tgz", + "integrity": "sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q==", + "dev": true, + "engines": { + "node": ">=0.6.19" + } + }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs": { + "name": "string-width", "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", @@ -5550,6 +4953,28 @@ "node": ">=8" } }, + "node_modules/strip-ansi-cjs": { + "name": "strip-ansi", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-final-newline": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, "node_modules/strip-json-comments": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", @@ -5562,16 +4987,96 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/sucrase": { + "version": "3.35.0", + "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.0.tgz", + "integrity": "sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==", + "dev": true, + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.2", + "commander": "^4.0.0", + "glob": "^10.3.10", + "lines-and-columns": "^1.1.6", + "mz": "^2.7.0", + "pirates": "^4.0.1", + "ts-interface-checker": "^0.1.9" + }, + "bin": { + "sucrase": "bin/sucrase", + "sucrase-node": "bin/sucrase-node" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/sucrase/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/sucrase/node_modules/commander": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", + "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, + "node_modules/sucrase/node_modules/glob": { + "version": "10.4.1", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.1.tgz", + "integrity": "sha512-2jelhlq3E4ho74ZyVLN03oKdAZVUa6UDZzFLVH1H7dnoax+y9qyaq8zBkfDIggjniU19z0wU18y16jMB2eyVIw==", + "dev": true, + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "path-scurry": "^1.11.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "engines": { + "node": ">=16 || 14 >=14.18" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/sucrase/node_modules/minimatch": { + "version": "9.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.4.tgz", + "integrity": "sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", "dev": true, "dependencies": { - "has-flag": "^3.0.0" + "has-flag": "^4.0.0" }, "engines": { - "node": ">=4" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" } }, "node_modules/supports-preserve-symlinks-flag": { @@ -5592,13 +5097,25 @@ "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", "dev": true }, - "node_modules/to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", + "node_modules/thenify": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", + "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==", "dev": true, + "dependencies": { + "any-promise": "^1.0.0" + } + }, + "node_modules/thenify-all": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz", + "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==", + "dev": true, + "dependencies": { + "thenify": ">= 3.1.0 < 4" + }, "engines": { - "node": ">=4" + "node": ">=0.8" } }, "node_modules/to-regex-range": { @@ -5635,12 +5152,115 @@ "node": ">=6" } }, + "node_modules/tr46": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-1.0.1.tgz", + "integrity": "sha512-dTpowEjclQ7Kgx5SdBkqRzVhERQXov8/l9Ft9dVM9fmg0W0KQSVaXX9T4i6twCPNtYiZM53lpSSUAwJbFPOHxA==", + "dev": true, + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/tr46/node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/tree-kill": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz", + "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==", + "dev": true, + "bin": { + "tree-kill": "cli.js" + } + }, + "node_modules/ts-interface-checker": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz", + "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==", + "dev": true + }, "node_modules/tslib": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", "dev": true }, + "node_modules/tsup": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/tsup/-/tsup-8.1.0.tgz", + "integrity": "sha512-UFdfCAXukax+U6KzeTNO2kAARHcWxmKsnvSPXUcfA1D+kU05XDccCrkffCQpFaWDsZfV0jMyTsxU39VfCp6EOg==", + "dev": true, + "dependencies": { + "bundle-require": "^4.0.0", + "cac": "^6.7.12", + "chokidar": "^3.5.1", + "debug": "^4.3.1", + "esbuild": "^0.21.4", + "execa": "^5.0.0", + "globby": "^11.0.3", + "joycon": "^3.0.1", + "postcss-load-config": "^4.0.1", + "resolve-from": "^5.0.0", + "rollup": "^4.0.2", + "source-map": "0.8.0-beta.0", + "sucrase": "^3.20.3", + "tree-kill": "^1.2.2" + }, + "bin": { + "tsup": "dist/cli-default.js", + "tsup-node": "dist/cli-node.js" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@microsoft/api-extractor": "^7.36.0", + "@swc/core": "^1", + "postcss": "^8.4.12", + "typescript": ">=4.5.0" + }, + "peerDependenciesMeta": { + "@microsoft/api-extractor": { + "optional": true + }, + "@swc/core": { + "optional": true + }, + "postcss": { + "optional": true + }, + "typescript": { + "optional": true + } + } + }, + "node_modules/tsup/node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/tsup/node_modules/source-map": { + "version": "0.8.0-beta.0", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.8.0-beta.0.tgz", + "integrity": "sha512-2ymg6oRBpebeZi9UUNsgQ89bhx01TcTkmNTGnNO88imTmbSgy4nfujrgVEFKWpMTEGA11EDkTt7mqObTPdigIA==", + "dev": true, + "dependencies": { + "whatwg-url": "^7.0.0" + }, + "engines": { + "node": ">= 8" + } + }, "node_modules/tsutils": { "version": "3.21.0", "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", @@ -5736,77 +5356,15 @@ "node_modules/undici-types": { "version": "5.26.5", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", - "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", - "dev": true - }, - "node_modules/unicode-canonical-property-names-ecmascript": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz", - "integrity": "sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/unicode-match-property-ecmascript": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz", - "integrity": "sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==", - "dev": true, - "dependencies": { - "unicode-canonical-property-names-ecmascript": "^2.0.0", - "unicode-property-aliases-ecmascript": "^2.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/unicode-match-property-value-ecmascript": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.1.0.tgz", - "integrity": "sha512-qxkjQt6qjg/mYscYMC0XKRn3Rh0wFPlfxB0xkt9CfyTvpX1Ra0+rAmdX2QyAobptSEvuy4RtpPRui6XkV+8wjA==", - "dev": true, - "engines": { - "node": ">=4" - } + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==" }, - "node_modules/unicode-property-aliases-ecmascript": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.1.0.tgz", - "integrity": "sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w==", + "node_modules/universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", "dev": true, "engines": { - "node": ">=4" - } - }, - "node_modules/update-browserslist-db": { - "version": "1.0.13", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz", - "integrity": "sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "dependencies": { - "escalade": "^3.1.1", - "picocolors": "^1.0.0" - }, - "bin": { - "update-browserslist-db": "cli.js" - }, - "peerDependencies": { - "browserslist": ">= 4.21.0" + "node": ">= 4.0.0" } }, "node_modules/uri-js": { @@ -5827,6 +5385,31 @@ "node": ">=6" } }, + "node_modules/url": { + "version": "0.11.3", + "resolved": "https://registry.npmjs.org/url/-/url-0.11.3.tgz", + "integrity": "sha512-6hxOLGfZASQK/cijlZnZJTq8OXAkt/3YGfQX45vvMYXpZoo8NdWZcY73K108Jf759lS1Bv/8wXnHDTSz17dSRw==", + "dev": true, + "dependencies": { + "punycode": "^1.4.1", + "qs": "^6.11.2" + } + }, + "node_modules/url/node_modules/qs": { + "version": "6.12.1", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.12.1.tgz", + "integrity": "sha512-zWmv4RSuB9r2mYQw3zxQuHWeU+42aKi1wWig/j4ele4ygELZ7PEO6MM7rim9oAQH2A5MWfsAVf/jPvTPgCbvUQ==", + "dev": true, + "dependencies": { + "side-channel": "^1.0.6" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/utf-8-validate": { "version": "5.0.10", "resolved": "https://registry.npmjs.org/utf-8-validate/-/utf-8-validate-5.0.10.tgz", @@ -5868,6 +5451,23 @@ "integrity": "sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==", "dev": true }, + "node_modules/webidl-conversions": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-4.0.2.tgz", + "integrity": "sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==", + "dev": true + }, + "node_modules/whatwg-url": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-7.1.0.tgz", + "integrity": "sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg==", + "dev": true, + "dependencies": { + "lodash.sortby": "^4.7.0", + "tr46": "^1.0.1", + "webidl-conversions": "^4.0.2" + } + }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", @@ -5921,6 +5521,57 @@ "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, + "node_modules/wrap-ansi-cjs": { + "name": "wrap-ansi", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, "node_modules/wrap-ansi/node_modules/ansi-styles": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", @@ -5990,11 +5641,23 @@ } }, "node_modules/yallist": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", - "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", "dev": true }, + "node_modules/yaml": { + "version": "2.4.5", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.4.5.tgz", + "integrity": "sha512-aBx2bnqDzVOyNKfsysjA2ms5ZlnjSAW2eG3/L5G/CSujfjLJTJsEw1bGw8kCf04KodQWk1pxlGnZ56CRxiawmg==", + "dev": true, + "bin": { + "yaml": "bin.mjs" + }, + "engines": { + "node": ">= 14" + } + }, "node_modules/yargs": { "version": "16.2.0", "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", diff --git a/package.json b/package.json index 3be080e..7990c79 100644 --- a/package.json +++ b/package.json @@ -2,10 +2,33 @@ "name": "rpc-websockets", "version": "8.0.1", "description": "JSON-RPC 2.0 implementation over WebSockets for Node.js", + "exports": { + "browser": { + "import": "./dist/index.browser.mjs", + "require": "./dist/index.browser.cjs", + "types": "./dist/index.browser.d.ts" + }, + "node": { + "import": "./dist/index.mjs", + "require": "./dist/index.cjs", + "types": "./dist/index.d.ts" + }, + "types": "./dist/index.d.ts" + }, + "browser": { + "./dist/index.cjs": "./dist/index.browser.cjs", + "./dist/index.mjs": "./dist/index.browser.mjs" + }, "main": "./dist/index.cjs", - "types": "./dist/index.d.cts", + "module": "./dist/index.mjs", + "types": "./dist/index.d.ts", + "type": "commonjs", + "files": [ + "dist/" + ], "scripts": { - "build": "tsc && mkdir -p ./dist && eslint --fix -c ./.eslintrc './src/**/*.cts' && ./build-browser-bundle.mjs", + "build": "npm run typecheck && mkdir -p ./dist && eslint --fix -c ./.eslintrc './src/**/*.ts' && parcel build", + "typecheck": "tsc", "pretest": "npm run-script build", "test": "mocha --exit test/*spec.js", "test:client": "mocha --exit test/client.spec.js", @@ -18,6 +41,10 @@ "url": "git+https://github.com/elpheria/rpc-websockets.git" }, "dependencies": { + "@swc/helpers": "^0.5.11", + "@types/uuid": "^8.3.4", + "@types/ws": "^8.2.2", + "buffer": "^6.0.3", "eventemitter3": "^4.0.7", "uuid": "^8.3.2", "ws": "^8.5.0" @@ -27,26 +54,21 @@ "utf-8-validate": "^5.0.2" }, "devDependencies": { - "@babel/core": "^7.24.5", - "@babel/plugin-transform-runtime": "^7.17.0", - "@babel/preset-env": "^7.16.11", - "@types/uuid": "^8.3.4", - "@types/ws": "^8.2.2", + "@microsoft/api-extractor": "^7.47.0", "@typescript-eslint/eslint-plugin": "^5.11.0", "@typescript-eslint/parser": "^5.11.0", "async": "^3.2.3", - "babel-eslint": "^10.1.0", "chai": "^4.3.6", "coveralls": "^3.1.1", - "esbuild": "^0.20.2", - "esbuild-plugin-babel": "^0.2.3", + "esbuild-plugin-polyfill-node": "^0.3.0", "eslint": "^8.8.0", "istanbul": "^0.4.5", "mocha": "^10.0.0", "mocha-lcov-reporter": "^1.3.0", - "typescript": "^4.5.5" + "tsup": "^8.1.0", + "typescript": "^4.5.5", + "url": "^0.11.3" }, - "browser": "./dist/index.browser.cjs", "keywords": [ "json", "rpc", diff --git a/src/index.browser-bundle.ts b/src/index.browser-bundle.ts new file mode 100644 index 0000000..33b78c6 --- /dev/null +++ b/src/index.browser-bundle.ts @@ -0,0 +1 @@ +export { Client } from "./index.browser.js" diff --git a/src/index.browser.cts b/src/index.browser.ts similarity index 53% rename from src/index.browser.cts rename to src/index.browser.ts index 46da16a..b649d38 100644 --- a/src/index.browser.cts +++ b/src/index.browser.ts @@ -1,8 +1,8 @@ "use strict" -import WebSocketBrowserImpl from "./lib/client/websocket.browser.cjs" -import CommonClient from "./lib/client.cjs" -import { IWSClientAdditionalOptions } from "./lib/client/client.types.cjs" +import { WebSocket } from "./lib/client/websocket.browser.js" +import { CommonClient } from "./lib/client.js" +import { IWSClientAdditionalOptions } from "./lib/client/client.types.js" export class Client extends CommonClient { @@ -12,21 +12,29 @@ export class Client extends CommonClient autoconnect = true, reconnect = true, reconnect_interval = 1000, - max_reconnects = 5 + max_reconnects = 5, }: IWSClientAdditionalOptions = {}, - generate_request_id?: (method: string, params: object | Array) => number + generate_request_id?: ( + method: string, + params: object | Array + ) => number ) { super( - WebSocketBrowserImpl, + WebSocket, address, { autoconnect, reconnect, reconnect_interval, - max_reconnects + max_reconnects, }, generate_request_id ) } -} \ No newline at end of file +} + +export * from "./lib/client.js" +export * from "./lib/client/websocket.browser.js" +export * from "./lib/client/client.types.js" +export * from "./lib/utils.js" diff --git a/src/index.cts b/src/index.cts deleted file mode 100644 index ae73a75..0000000 --- a/src/index.cts +++ /dev/null @@ -1,40 +0,0 @@ -"use strict" - -import WebSocket from "./lib/client/websocket.cjs" -import CommonClient from "./lib/client.cjs" -import { - NodeWebSocketTypeOptions, - IWSClientAdditionalOptions, - ICommonWebSocketFactory -} from "./lib/client/client.types.cjs" - -export class Client extends CommonClient -{ - constructor( - address = "ws://localhost:8080", - { - autoconnect = true, - reconnect = true, - reconnect_interval = 1000, - max_reconnects = 5, - ...rest_options - }: IWSClientAdditionalOptions & NodeWebSocketTypeOptions = {}, - generate_request_id?: (method: string, params: object | Array) => number - ) - { - super( - WebSocket as ICommonWebSocketFactory, - address, - { - autoconnect, - reconnect, - reconnect_interval, - max_reconnects, - ...rest_options - }, - generate_request_id - ) - } -} - -export {default as Server} from "./lib/server.cjs" diff --git a/src/index.ts b/src/index.ts new file mode 100644 index 0000000..a148cb8 --- /dev/null +++ b/src/index.ts @@ -0,0 +1,47 @@ +"use strict" + +import { WebSocket } from "./lib/client/websocket.js" +import { CommonClient } from "./lib/client.js" +import { + NodeWebSocketTypeOptions, + IWSClientAdditionalOptions, + ICommonWebSocketFactory, +} from "./lib/client/client.types.js" + +export class Client extends CommonClient +{ + constructor( + address = "ws://localhost:8080", + { + autoconnect = true, + reconnect = true, + reconnect_interval = 1000, + max_reconnects = 5, + ...rest_options + }: IWSClientAdditionalOptions & NodeWebSocketTypeOptions = {}, + generate_request_id?: ( + method: string, + params: object | Array + ) => number + ) + { + super( + WebSocket as ICommonWebSocketFactory, + address, + { + autoconnect, + reconnect, + reconnect_interval, + max_reconnects, + ...rest_options, + }, + generate_request_id + ) + } +} + +export * from "./lib/client.js" +export * from "./lib/client/websocket.js" +export * from "./lib/client/client.types.js" +export * from "./lib/server.js" +export * from "./lib/utils.js" \ No newline at end of file diff --git a/src/lib/client.cts b/src/lib/client.ts similarity index 58% rename from src/lib/client.cts rename to src/lib/client.ts index 54bffcf..0850ff2 100644 --- a/src/lib/client.cts +++ b/src/lib/client.ts @@ -7,35 +7,34 @@ "use strict" import NodeWebSocket from "ws" -// @ts-ignore import { EventEmitter } from "eventemitter3" import { ICommonWebSocket, IWSClientAdditionalOptions, NodeWebSocketType, - ICommonWebSocketFactory -} from "./client/client.types.cjs" + ICommonWebSocketFactory, +} from "./client/client.types.js" -import { DataPack, DefaultDataPack } from "./utils.cjs" +import { DataPack, DefaultDataPack } from "./utils.js" interface IQueueElement { - promise: [ - Parameters[0]>[0], - Parameters[0]>[1] - ]; - timeout?: ReturnType; + promise: [ + Parameters[0]>[0], + Parameters[0]>[1] + ]; + timeout?: ReturnType; } export interface IQueue { - [x: number]: IQueueElement; + [x: number]: IQueueElement; } export interface IWSRequestParams { - [x: string]: any; - [x: number]: any; + [x: string]: any; + [x: number]: any; } -export default class CommonClient extends EventEmitter +export class CommonClient extends EventEmitter { private address: string private rpc_id: number @@ -47,23 +46,27 @@ export default class CommonClient extends EventEmitter private reconnect_timer_id: NodeJS.Timeout private reconnect_interval: number private max_reconnects: number - private rest_options: IWSClientAdditionalOptions & NodeWebSocket.ClientOptions + private rest_options: IWSClientAdditionalOptions & + NodeWebSocket.ClientOptions private current_reconnects: number - private generate_request_id: (method: string, params: object | Array) => number + private generate_request_id: ( + method: string, + params: object | Array + ) => number private socket: ICommonWebSocket private webSocketFactory: ICommonWebSocketFactory private dataPack: DataPack /** - * Instantiate a Client class. - * @constructor - * @param {webSocketFactory} webSocketFactory - factory method for WebSocket - * @param {String} address - url to a websocket server - * @param {Object} options - ws options object with reconnect parameters - * @param {Function} generate_request_id - custom generation request Id - * @param {DataPack} dataPack - data pack contains encoder and decoder - * @return {CommonClient} - */ + * Instantiate a Client class. + * @constructor + * @param {webSocketFactory} webSocketFactory - factory method for WebSocket + * @param {String} address - url to a websocket server + * @param {Object} options - ws options object with reconnect parameters + * @param {Function} generate_request_id - custom generation request Id + * @param {DataPack} dataPack - data pack contains encoder and decoder + * @return {CommonClient} + */ constructor( webSocketFactory: ICommonWebSocketFactory, address = "ws://localhost:8080", @@ -74,7 +77,10 @@ export default class CommonClient extends EventEmitter max_reconnects = 5, ...rest_options } = {}, - generate_request_id?: (method: string, params: object | Array) => number, + generate_request_id?: ( + method: string, + params: object | Array + ) => number, dataPack?: DataPack ) { @@ -96,10 +102,8 @@ export default class CommonClient extends EventEmitter this.current_reconnects = 0 this.generate_request_id = generate_request_id || (() => ++this.rpc_id) - if (!dataPack) - this.dataPack = new DefaultDataPack() - else - this.dataPack = dataPack + if (!dataPack) this.dataPack = new DefaultDataPack() + else this.dataPack = dataPack if (this.autoconnect) this._connect(this.address, { @@ -107,38 +111,37 @@ export default class CommonClient extends EventEmitter reconnect: this.reconnect, reconnect_interval: this.reconnect_interval, max_reconnects: this.max_reconnects, - ...this.rest_options + ...this.rest_options, }) } /** - * Connects to a defined server if not connected already. - * @method - * @return {Undefined} - */ + * Connects to a defined server if not connected already. + * @method + * @return {Undefined} + */ connect() { - if (this.socket) - return + if (this.socket) return this._connect(this.address, { autoconnect: this.autoconnect, reconnect: this.reconnect, reconnect_interval: this.reconnect_interval, max_reconnects: this.max_reconnects, - ...this.rest_options + ...this.rest_options, }) } /** - * Calls a registered RPC method on server. - * @method - * @param {String} method - RPC method name - * @param {Object|Array} params - optional method parameters - * @param {Number} timeout - RPC reply timeout value - * @param {Object} ws_opts - options passed to ws - * @return {Promise} - */ + * Calls a registered RPC method on server. + * @method + * @param {String} method - RPC method name + * @param {Object|Array} params - optional method parameters + * @param {Number} timeout - RPC reply timeout value + * @param {Object} ws_opts - options passed to ws + * @return {Promise} + */ call( method: string, params?: IWSRequestParams, @@ -154,8 +157,7 @@ export default class CommonClient extends EventEmitter return new Promise((resolve, reject) => { - if (!this.ready) - return reject(new Error("socket not ready")) + if (!this.ready) return reject(new Error("socket not ready")) const rpc_id = this.generate_request_id(method, params) @@ -163,13 +165,12 @@ export default class CommonClient extends EventEmitter jsonrpc: "2.0", method: method, params: params || undefined, - id: rpc_id + id: rpc_id, } this.socket.send(this.dataPack.encode(message), ws_opts, (error) => { - if (error) - return reject(error) + if (error) return reject(error) this.queue[rpc_id] = { promise: [resolve, reject] } @@ -186,55 +187,52 @@ export default class CommonClient extends EventEmitter } /** - * Logins with the other side of the connection. - * @method - * @param {Object} params - Login credentials object - * @return {Promise} - */ + * Logins with the other side of the connection. + * @method + * @param {Object} params - Login credentials object + * @return {Promise} + */ async login(params: IWSRequestParams) { const resp = await this.call("rpc.login", params) - if (!resp) - throw new Error("authentication failed") + if (!resp) throw new Error("authentication failed") return resp } /** - * Fetches a list of client's methods registered on server. - * @method - * @return {Array} - */ + * Fetches a list of client's methods registered on server. + * @method + * @return {Array} + */ async listMethods() { return await this.call("__listMethods") } /** - * Sends a JSON-RPC 2.0 notification to server. - * @method - * @param {String} method - RPC method name - * @param {Object} params - optional method parameters - * @return {Promise} - */ + * Sends a JSON-RPC 2.0 notification to server. + * @method + * @param {String} method - RPC method name + * @param {Object} params - optional method parameters + * @return {Promise} + */ notify(method: string, params?: IWSRequestParams) { return new Promise((resolve, reject) => { - if (!this.ready) - return reject(new Error("socket not ready")) + if (!this.ready) return reject(new Error("socket not ready")) const message = { jsonrpc: "2.0", method: method, - params + params, } this.socket.send(this.dataPack.encode(message), (error) => { - if (error) - return reject(error) + if (error) return reject(error) resolve() }) @@ -242,36 +240,36 @@ export default class CommonClient extends EventEmitter } /** - * Subscribes for a defined event. - * @method - * @param {String|Array} event - event name - * @return {Undefined} - * @throws {Error} - */ + * Subscribes for a defined event. + * @method + * @param {String|Array} event - event name + * @return {Undefined} + * @throws {Error} + */ async subscribe(event: string | Array) { - if (typeof event === "string") - event = [ event ] + if (typeof event === "string") event = [event] const result = await this.call("rpc.on", event) if (typeof event === "string" && result[event] !== "ok") - throw new Error("Failed subscribing to an event '" + event + "' with: " + result[event]) + throw new Error( + "Failed subscribing to an event '" + event + "' with: " + result[event] + ) return result } /** - * Unsubscribes from a defined event. - * @method - * @param {String|Array} event - event name - * @return {Undefined} - * @throws {Error} - */ + * Unsubscribes from a defined event. + * @method + * @param {String|Array} event - event name + * @return {Undefined} + * @throws {Error} + */ async unsubscribe(event: string | Array) { - if (typeof event === "string") - event = [ event ] + if (typeof event === "string") event = [event] const result = await this.call("rpc.off", event) @@ -282,58 +280,58 @@ export default class CommonClient extends EventEmitter } /** - * Closes a WebSocket connection gracefully. - * @method - * @param {Number} code - socket close code - * @param {String} data - optional data to be sent before closing - * @return {Undefined} - */ + * Closes a WebSocket connection gracefully. + * @method + * @param {Number} code - socket close code + * @param {String} data - optional data to be sent before closing + * @return {Undefined} + */ close(code?: number, data?: string) { this.socket.close(code || 1000, data) } /** - * Enable / disable automatic reconnection. - * @method - * @param {Boolean} reconnect - enable / disable reconnection - * @return {Undefined} - */ + * Enable / disable automatic reconnection. + * @method + * @param {Boolean} reconnect - enable / disable reconnection + * @return {Undefined} + */ setAutoReconnect(reconnect: boolean) { this.reconnect = reconnect } /** - * Set the interval between reconnection attempts. - * @method - * @param {Number} interval - reconnection interval in milliseconds - * @return {Undefined} - */ + * Set the interval between reconnection attempts. + * @method + * @param {Number} interval - reconnection interval in milliseconds + * @return {Undefined} + */ setReconnectInterval(interval: number) { this.reconnect_interval = interval } /** - * Set the maximum number of reconnection attempts. - * @method - * @param {Number} max_reconnects - maximum reconnection attempts - * @return {Undefined} - */ + * Set the maximum number of reconnection attempts. + * @method + * @param {Number} max_reconnects - maximum reconnection attempts + * @return {Undefined} + */ setMaxReconnects(max_reconnects: number) { this.max_reconnects = max_reconnects } /** - * Connection/Message handler. - * @method - * @private - * @param {String} address - WebSocket API address - * @param {Object} options - ws options object - * @return {Undefined} - */ + * Connection/Message handler. + * @method + * @private + * @param {String} address - WebSocket API address + * @param {Object} options - ws options object + * @return {Undefined} + */ private _connect( address: string, options: IWSClientAdditionalOptions & NodeWebSocket.ClientOptions @@ -349,14 +347,19 @@ export default class CommonClient extends EventEmitter this.current_reconnects = 0 }) - this.socket.addEventListener("message", ({data: message}) => + this.socket.addEventListener("message", ({ data: message }) => { if (message instanceof ArrayBuffer) message = Buffer.from(message).toString() - try { message = this.dataPack.decode(message) } - - catch (error) { return } + try + { + message = this.dataPack.decode(message) + } + catch (error) + { + return + } // check if any listeners are attached and forward event if (message.notification && this.listeners(message.notification).length) @@ -366,16 +369,19 @@ export default class CommonClient extends EventEmitter const args = [message.notification] - if (message.params.constructor === Object) - args.push(message.params) + if (message.params.constructor === Object) args.push(message.params) + // using for-loop instead of unshift/spread because performance is better else - // using for-loop instead of unshift/spread because performance is better for (let i = 0; i < message.params.length; i++) args.push(message.params[i]) // run as microtask so that pending queue messages are resolved first // eslint-disable-next-line prefer-spread - return Promise.resolve().then(() => { this.emit.apply(this, args) }) + return Promise.resolve().then(() => + { + // eslint-disable-next-line prefer-spread + this.emit.apply(this, args) + }) } if (!this.queue[message.id]) @@ -395,39 +401,42 @@ export default class CommonClient extends EventEmitter // reject early since server's response is invalid if ("error" in message === "result" in message) - this.queue[message.id].promise[1](new Error( - "Server response malformed. Response must include either \"result\"" + - " or \"error\", but not both." - )) + this.queue[message.id].promise[1]( + new Error( + "Server response malformed. Response must include either \"result\"" + + " or \"error\", but not both." + ) + ) if (this.queue[message.id].timeout) clearTimeout(this.queue[message.id].timeout) - if (message.error) - this.queue[message.id].promise[1](message.error) - else - this.queue[message.id].promise[0](message.result) + if (message.error) this.queue[message.id].promise[1](message.error) + else this.queue[message.id].promise[0](message.result) delete this.queue[message.id] }) this.socket.addEventListener("error", (error) => this.emit("error", error)) - this.socket.addEventListener("close", ({code, reason}) => + this.socket.addEventListener("close", ({ code, reason }) => { - if (this.ready) // Delay close event until internal state is updated + if (this.ready) + // Delay close event until internal state is updated setTimeout(() => this.emit("close", code, reason), 0) this.ready = false this.socket = undefined - if (code === 1000) - return + if (code === 1000) return this.current_reconnects++ - if (this.reconnect && ((this.max_reconnects > this.current_reconnects) || - this.max_reconnects === 0)) + if ( + this.reconnect && + (this.max_reconnects > this.current_reconnects || + this.max_reconnects === 0) + ) this.reconnect_timer_id = setTimeout( () => this._connect(address, options), this.reconnect_interval diff --git a/src/lib/client/client.types.cts b/src/lib/client/client.types.ts similarity index 100% rename from src/lib/client/client.types.cts rename to src/lib/client/client.types.ts diff --git a/src/lib/client/websocket.browser.cts b/src/lib/client/websocket.browser.ts similarity index 60% rename from src/lib/client/websocket.browser.cts rename to src/lib/client/websocket.browser.ts index a7836e8..9948998 100644 --- a/src/lib/client/websocket.browser.cts +++ b/src/lib/client/websocket.browser.ts @@ -6,23 +6,24 @@ "use strict" import { EventEmitter } from "eventemitter3" + import { BrowserWebSocketType, NodeWebSocketType, - IWSClientAdditionalOptions -} from "./client.types.cjs" + IWSClientAdditionalOptions, +} from "./client.types.js" class WebSocketBrowserImpl extends EventEmitter { socket: BrowserWebSocketType /** Instantiate a WebSocket class - * @constructor - * @param {String} address - url to a websocket server - * @param {(Object)} options - websocket options - * @param {(String|Array)} protocols - a list of protocols - * @return {WebSocketBrowserImpl} - returns a WebSocket instance - */ + * @constructor + * @param {String} address - url to a websocket server + * @param {(Object)} options - websocket options + * @param {(String|Array)} protocols - a list of protocols + * @return {WebSocketBrowserImpl} - returns a WebSocket instance + */ constructor(address: string, options: {}, protocols?: string | string[]) { super() @@ -39,16 +40,18 @@ class WebSocketBrowserImpl extends EventEmitter } /** - * Sends data through a websocket connection - * @method - * @param {(String|Object)} data - data to be sent via websocket - * @param {Object} optionsOrCallback - ws options - * @param {Function} callback - a callback called once the data is sent - * @return {Undefined} - */ + * Sends data through a websocket connection + * @method + * @param {(String|Object)} data - data to be sent via websocket + * @param {Object} optionsOrCallback - ws options + * @param {Function} callback - a callback called once the data is sent + * @return {Undefined} + */ send( data: Parameters[0], - optionsOrCallback: (error?: Error) => void | Parameters[1], + optionsOrCallback: ( + error?: Error + ) => void | Parameters[1], callback?: () => void ) { @@ -59,17 +62,20 @@ class WebSocketBrowserImpl extends EventEmitter this.socket.send(data) cb() } - catch (error) { cb(error) } + catch (error) + { + cb(error) + } } /** - * Closes an underlying socket - * @method - * @param {Number} code - status code explaining why the connection is being closed - * @param {String} reason - a description why the connection is closing - * @return {Undefined} - * @throws {Error} - */ + * Closes an underlying socket + * @method + * @param {Number} code - status code explaining why the connection is being closed + * @param {String} reason - a description why the connection is closing + * @return {Undefined} + * @throws {Error} + */ close(code?: number, reason?: string) { this.socket.close(code, reason) @@ -92,7 +98,10 @@ class WebSocketBrowserImpl extends EventEmitter * @param {(Object)} options - websocket options * @return {Undefined} */ -export default function(address: string, options: IWSClientAdditionalOptions) +export function WebSocket( + address: string, + options: IWSClientAdditionalOptions +) { return new WebSocketBrowserImpl(address, options) } diff --git a/src/lib/client/websocket.cts b/src/lib/client/websocket.ts similarity index 54% rename from src/lib/client/websocket.cts rename to src/lib/client/websocket.ts index 23f0d64..5da317b 100644 --- a/src/lib/client/websocket.cts +++ b/src/lib/client/websocket.ts @@ -2,8 +2,9 @@ "use strict" -import WebSocket from "ws" -import { IWSClientAdditionalOptions } from "./client.types.cjs" +import WebSocketImpl from "ws" + +import { IWSClientAdditionalOptions } from "./client.types.js" /** * factory method for common WebSocket instance @@ -12,10 +13,10 @@ import { IWSClientAdditionalOptions } from "./client.types.cjs" * @param {(Object)} options - websocket options * @return {Undefined} */ -export default function( +export function WebSocket( address: string, - options: IWSClientAdditionalOptions & WebSocket.ClientOptions + options: IWSClientAdditionalOptions & WebSocketImpl.ClientOptions ) { - return new WebSocket(address, options) + return new WebSocketImpl(address, options) } diff --git a/src/lib/server.cts b/src/lib/server.ts similarity index 52% rename from src/lib/server.cts rename to src/lib/server.ts index 0aad2ff..bf563b9 100644 --- a/src/lib/server.cts +++ b/src/lib/server.ts @@ -5,93 +5,99 @@ "use strict" -// @ts-ignore import { EventEmitter } from "eventemitter3" -import NodeWebSocket, { Server as WebSocketServer } from "ws" +import url from "node:url" import { v1 as uuidv1 } from "uuid" -import url from "url" +import NodeWebSocket, { WebSocketServer } from "ws" -import * as utils from "./utils.cjs" +import { DataPack, DefaultDataPack } from "./utils.js" interface INamespaceEvent { - [x: string]: { - sockets: Array; - protected: boolean; - }; + [x: string]: { + sockets: Array; + protected: boolean; + }; } interface IMethod { - public: () => void; - protected: () => void; + public: () => void; + protected: () => void; } interface IEvent { - public: () => void; - protected: () => void; + public: () => void; + protected: () => void; +} + +interface IRPCError { + code: number; + message: string; + data?: string; } interface IRPCMethodParams { - [x: string]: any; + [x: string]: any; } interface IRPCMethod { - [x: string]: { - fn: (params: IRPCMethodParams, socket_id: string) => any; - protected: boolean; - }; + [x: string]: { + fn: (params: IRPCMethodParams, socket_id: string) => any; + protected: boolean; + }; } interface INamespace { - [x: string]: { - rpc_methods: IRPCMethod; - clients: Map; - events: INamespaceEvent; - }; + [x: string]: { + rpc_methods: IRPCMethod; + clients: Map; + events: INamespaceEvent; + }; } interface IClientWebSocket extends NodeWebSocket { - _id: string; - _authenticated: boolean; + _id: string; + _authenticated: boolean; } interface IRPCResult { - [x: string]: string; + [x: string]: string; } -export default class Server extends EventEmitter +export class Server extends EventEmitter { private namespaces: INamespace - private dataPack: utils.DataPack + private dataPack: DataPack wss: InstanceType /** - * Instantiate a Server class. - * @constructor - * @param {Object} options - ws constructor's parameters with rpc - * @param {DataPack} dataPack - data pack contains encoder and decoder - * @return {Server} - returns a new Server instance - */ - constructor(options: NodeWebSocket.ServerOptions, dataPack?: utils.DataPack) + * Instantiate a Server class. + * @constructor + * @param {Object} options - ws constructor's parameters with rpc + * @param {DataPack} dataPack - data pack contains encoder and decoder + * @return {Server} - returns a new Server instance + */ + constructor( + options: NodeWebSocket.ServerOptions, + dataPack?: DataPack + ) { super() /** - * Stores all connected sockets with a universally unique identifier - * in the appropriate namespace. - * Stores all rpc methods to specific namespaces. "/" by default. - * Stores all events as keys and subscribed users in array as value - * @private - * @name namespaces - * @param {Object} namespaces.rpc_methods - * @param {Map} namespaces.clients - * @param {Object} namespaces.events - */ + * Stores all connected sockets with a universally unique identifier + * in the appropriate namespace. + * Stores all rpc methods to specific namespaces. "/" by default. + * Stores all events as keys and subscribed users in array as value + * @private + * @name namespaces + * @param {Object} namespaces.rpc_methods + * @param {Map} namespaces.clients + * @param {Object} namespaces.events + */ this.namespaces = {} - if (!dataPack) - this.dataPack = new utils.DefaultDataPack() - else - this.dataPack = dataPack + if (!dataPack) this.dataPack = new DefaultDataPack() + else this.dataPack = dataPack this.wss = new WebSocketServer(options) @@ -102,10 +108,8 @@ export default class Server extends EventEmitter const u = url.parse(request.url, true) const ns = u.pathname - if (u.query.socket_id) - socket._id = u.query.socket_id as string - else - socket._id = uuidv1() + if (u.query.socket_id) socket._id = u.query.socket_id as string + else socket._id = uuidv1() // unauthenticated by default socket["_authenticated"] = false @@ -120,7 +124,9 @@ export default class Server extends EventEmitter for (const event of Object.keys(this.namespaces[ns].events)) { - const index = this.namespaces[ns].events[event].sockets.indexOf(socket._id) + const index = this.namespaces[ns].events[event].sockets.indexOf( + socket._id + ) if (index >= 0) this.namespaces[ns].events[event].sockets.splice(index, 1) @@ -143,97 +149,104 @@ export default class Server extends EventEmitter } /** - * Registers an RPC method. - * @method - * @param {String} name - method name - * @param {Function} fn - a callee function - * @param {String} ns - namespace identifier - * @throws {TypeError} - * @return {Object} - returns an IMethod object - */ - register(name: string, fn: (params: IRPCMethodParams, socket_id: string) => void, ns = "/") + * Registers an RPC method. + * @method + * @param {String} name - method name + * @param {Function} fn - a callee function + * @param {String} ns - namespace identifier + * @throws {TypeError} + * @return {Object} - returns an IMethod object + */ + register( + name: string, + fn: (params: IRPCMethodParams, socket_id: string) => void, + ns = "/" + ) { if (!this.namespaces[ns]) this._generateNamespace(ns) this.namespaces[ns].rpc_methods[name] = { fn: fn, - protected: false + protected: false, } return { protected: () => this._makeProtectedMethod(name, ns), - public: () => this._makePublicMethod(name, ns) + public: () => this._makePublicMethod(name, ns), } as IMethod } /** - * Sets an auth method. - * @method - * @param {Function} fn - an arbitrary auth method - * @param {String} ns - namespace identifier - * @throws {TypeError} - * @return {Undefined} - */ - setAuth(fn: (params: IRPCMethodParams, socket_id: string) => Promise, ns = "/") + * Sets an auth method. + * @method + * @param {Function} fn - an arbitrary auth method + * @param {String} ns - namespace identifier + * @throws {TypeError} + * @return {Undefined} + */ + setAuth( + fn: (params: IRPCMethodParams, socket_id: string) => Promise, + ns = "/" + ) { this.register("rpc.login", fn, ns) } /** - * Marks an RPC method as protected. - * @method - * @param {String} name - method name - * @param {String} ns - namespace identifier - * @return {Undefined} - */ + * Marks an RPC method as protected. + * @method + * @param {String} name - method name + * @param {String} ns - namespace identifier + * @return {Undefined} + */ private _makeProtectedMethod(name: string, ns = "/") { this.namespaces[ns].rpc_methods[name].protected = true } /** - * Marks an RPC method as public. - * @method - * @param {String} name - method name - * @param {String} ns - namespace identifier - * @return {Undefined} - */ + * Marks an RPC method as public. + * @method + * @param {String} name - method name + * @param {String} ns - namespace identifier + * @return {Undefined} + */ private _makePublicMethod(name: string, ns = "/") { this.namespaces[ns].rpc_methods[name].protected = false } /** - * Marks an event as protected. - * @method - * @param {String} name - event name - * @param {String} ns - namespace identifier - * @return {Undefined} - */ + * Marks an event as protected. + * @method + * @param {String} name - event name + * @param {String} ns - namespace identifier + * @return {Undefined} + */ private _makeProtectedEvent(name: string, ns = "/") { this.namespaces[ns].events[name].protected = true } /** - * Marks an event as public. - * @method - * @param {String} name - event name - * @param {String} ns - namespace identifier - * @return {Undefined} - */ + * Marks an event as public. + * @method + * @param {String} name - event name + * @param {String} ns - namespace identifier + * @return {Undefined} + */ private _makePublicEvent(name: string, ns = "/") { this.namespaces[ns].events[name].protected = false } /** - * Removes a namespace and closes all connections - * @method - * @param {String} ns - namespace identifier - * @throws {TypeError} - * @return {Undefined} - */ + * Removes a namespace and closes all connections + * @method + * @param {String} ns - namespace identifier + * @throws {TypeError} + * @return {Undefined} + */ closeNamespace(ns: string) { const namespace = this.namespaces[ns] @@ -243,21 +256,20 @@ export default class Server extends EventEmitter delete namespace.rpc_methods delete namespace.events - for (const socket of namespace.clients.values()) - socket.close() + for (const socket of namespace.clients.values()) socket.close() delete this.namespaces[ns] } } /** - * Creates a new event that can be emitted to clients. - * @method - * @param {String} name - event name - * @param {String} ns - namespace identifier - * @throws {TypeError} - * @return {Object} - returns an IEvent object - */ + * Creates a new event that can be emitted to clients. + * @method + * @param {String} name - event name + * @param {String} ns - namespace identifier + * @throws {TypeError} + * @return {Object} - returns an IEvent object + */ event(name: string, ns = "/"): IEvent { if (!this.namespaces[ns]) this._generateNamespace(ns) @@ -271,7 +283,7 @@ export default class Server extends EventEmitter this.namespaces[ns].events[name] = { sockets: [], - protected: false + protected: false, } // forward emitted event to subscribers @@ -285,29 +297,30 @@ export default class Server extends EventEmitter { const socket = this.namespaces[ns].clients.get(socket_id) - if (!socket) - continue + if (!socket) continue - socket.send(this.dataPack.encode({ - notification: name, - params - })) + socket.send( + this.dataPack.encode({ + notification: name, + params, + }) + ) } }) return { protected: () => this._makeProtectedEvent(name, ns), - public: () => this._makePublicEvent(name, ns) + public: () => this._makePublicEvent(name, ns), } } /** - * Returns a requested namespace object - * @method - * @param {String} name - namespace identifier - * @throws {TypeError} - * @return {Object} - namespace object - */ + * Returns a requested namespace object + * @method + * @param {String} name - namespace identifier + * @throws {TypeError} + * @return {Object} - namespace object + */ of(name: string) { if (!this.namespaces[name]) this._generateNamespace(name) @@ -316,7 +329,10 @@ export default class Server extends EventEmitter return { // self.register convenience method - register(fn_name: string, fn: (params: IRPCMethodParams) => void): IMethod + register( + fn_name: string, + fn: (params: IRPCMethodParams) => void + ): IMethod { if (arguments.length !== 2) throw new Error("must provide exactly two arguments") @@ -349,74 +365,79 @@ export default class Server extends EventEmitter }, /** - * Emits a specified event to this namespace. - * @inner - * @method - * @param {String} event - event name - * @param {Array} params - event parameters - * @return {Undefined} - */ + * Emits a specified event to this namespace. + * @inner + * @method + * @param {String} event - event name + * @param {Array} params - event parameters + * @return {Undefined} + */ emit(event: string, ...params: Array) { - const socket_ids = [ ...self.namespaces[name].clients.keys() ] + const socket_ids = [...self.namespaces[name].clients.keys()] - for (let i = 0, id; id = socket_ids[i]; ++i) + for (let i = 0, id; (id = socket_ids[i]); ++i) { - self.namespaces[name].clients.get(id).send(self.dataPack.encode({ - notification: event, - params: params || [] - })) + self.namespaces[name].clients.get(id).send( + self.dataPack.encode({ + notification: event, + params: params || [], + }) + ) } }, /** - * Returns a name of this namespace. - * @inner - * @method - * @kind constant - * @return {String} - */ + * Returns a name of this namespace. + * @inner + * @method + * @kind constant + * @return {String} + */ get name() { return name }, /** - * Returns a hash of websocket objects connected to this namespace. - * @inner - * @method - * @return {Object} - */ + * Returns a hash of websocket objects connected to this namespace. + * @inner + * @method + * @return {Object} + */ connected() { - const socket_ids = [ ...self.namespaces[name].clients.keys() ] - - return socket_ids.reduce((acc, curr) => ({ - ...acc, - [curr]: self.namespaces[name].clients.get(curr) - }), {}) + const socket_ids = [...self.namespaces[name].clients.keys()] + + return socket_ids.reduce( + (acc, curr) => ({ + ...acc, + [curr]: self.namespaces[name].clients.get(curr), + }), + {} + ) }, /** - * Returns a list of client unique identifiers connected to this namespace. - * @inner - * @method - * @return {Array} - */ + * Returns a list of client unique identifiers connected to this namespace. + * @inner + * @method + * @return {Array} + */ clients() { return self.namespaces[name] - } + }, } } /** - * Lists all created events in a given namespace. Defaults to "/". - * @method - * @param {String} ns - namespaces identifier - * @readonly - * @return {Array} - returns a list of created events - */ + * Lists all created events in a given namespace. Defaults to "/". + * @method + * @param {String} ns - namespaces identifier + * @readonly + * @return {Array} - returns a list of created events + */ eventList(ns = "/") { if (!this.namespaces[ns]) return [] @@ -425,27 +446,27 @@ export default class Server extends EventEmitter } /** - * Creates a JSON-RPC 2.0 compliant error - * @method - * @param {Number} code - indicates the error type that occurred - * @param {String} message - provides a short description of the error - * @param {String|Object} data - details containing additional information about the error - * @return {Object} - */ + * Creates a JSON-RPC 2.0 compliant error + * @method + * @param {Number} code - indicates the error type that occurred + * @param {String} message - provides a short description of the error + * @param {String|Object} data - details containing additional information about the error + * @return {Object} + */ createError(code: number, message: string, data: string | object) { return { code: code, message: message, - data: data || null + data: data || null, } } /** - * Closes the server and terminates all clients. - * @method - * @return {Promise} - */ + * Closes the server and terminates all clients. + * @method + * @return {Promise} + */ close() { return new Promise((resolve, reject) => @@ -456,21 +477,23 @@ export default class Server extends EventEmitter this.emit("close") resolve() } - - catch (error) { reject(error) } + catch (error) + { + reject(error) + } }) } /** - * Handles all WebSocket JSON RPC 2.0 requests. - * @private - * @param {Object} socket - ws socket instance - * @param {String} ns - namespaces identifier - * @return {Undefined} - */ + * Handles all WebSocket JSON RPC 2.0 requests. + * @private + * @param {Object} socket - ws socket instance + * @param {String} ns - namespaces identifier + * @return {Undefined} + */ private _handleRPC(socket: IClientWebSocket, ns = "/") { - socket.on("message", async(data: any) => + socket.on("message", async (data: any) => { const msg_options: Parameters[1] = {} @@ -481,30 +504,37 @@ export default class Server extends EventEmitter data = Buffer.from(data).toString() } - if (socket.readyState !== 1) - return // TODO: should have debug logs here + if (socket.readyState !== 1) return // TODO: should have debug logs here let parsedData: any - try { parsedData = this.dataPack.decode(data as string) } - + try + { + parsedData = this.dataPack.decode(data as string) + } catch (error) { - return socket.send(this.dataPack.encode({ - jsonrpc: "2.0", - error: utils.createError(-32700, error.toString()), - id: null - }), msg_options) + return socket.send( + this.dataPack.encode({ + jsonrpc: "2.0", + error: createError(-32700, error.toString()), + id: null, + }), + msg_options + ) } if (Array.isArray(parsedData)) { if (!parsedData.length) - return socket.send(this.dataPack.encode({ - jsonrpc: "2.0", - error: utils.createError(-32600, "Invalid array"), - id: null - }), msg_options) + return socket.send( + this.dataPack.encode({ + jsonrpc: "2.0", + error: createError(-32600, "Invalid array"), + id: null, + }), + msg_options + ) const responses = [] @@ -512,70 +542,67 @@ export default class Server extends EventEmitter { const response = await this._runMethod(message, socket._id, ns) - if (!response) - continue + if (!response) continue responses.push(response) } - if (!responses.length) - return + if (!responses.length) return return socket.send(this.dataPack.encode(responses), msg_options) } const response = await this._runMethod(parsedData, socket._id, ns) - if (!response) - return + if (!response) return return socket.send(this.dataPack.encode(response), msg_options) }) } /** - * Runs a defined RPC method. - * @private - * @param {Object} message - a message received - * @param {Object} socket_id - user's socket id - * @param {String} ns - namespaces identifier - * @return {Object|undefined} - */ + * Runs a defined RPC method. + * @private + * @param {Object} message - a message received + * @param {Object} socket_id - user's socket id + * @param {String} ns - namespaces identifier + * @return {Object|undefined} + */ private async _runMethod(message: any, socket_id: string, ns = "/") { if (typeof message !== "object" || message === null) return { jsonrpc: "2.0", - error: utils.createError(-32600), - id: null + error: createError(-32600), + id: null, } if (message.jsonrpc !== "2.0") return { jsonrpc: "2.0", - error: utils.createError(-32600, "Invalid JSON RPC version"), - id: message.id || null + error: createError(-32600, "Invalid JSON RPC version"), + id: message.id || null, } if (!message.method) return { jsonrpc: "2.0", - error: utils.createError(-32602, "Method not specified"), - id: message.id || null + error: createError(-32602, "Method not specified"), + id: message.id || null, } if (typeof message.method !== "string") return { jsonrpc: "2.0", - error: utils.createError(-32600, "Invalid method name"), - id: message.id || null + error: createError(-32600, "Invalid method name"), + id: message.id || null, } if (message.params && typeof message.params === "string") return { jsonrpc: "2.0", - error: utils.createError(-32600), - id: message.id || null + error: createError(-32600), + id: message.id || null, } if (message.method === "rpc.on") @@ -583,8 +610,8 @@ export default class Server extends EventEmitter if (!message.params) return { jsonrpc: "2.0", - error: utils.createError(-32000), - id: message.id || null + error: createError(-32000), + id: message.id || null, } const results: IRPCMethodParams = {} @@ -603,17 +630,20 @@ export default class Server extends EventEmitter } // reject request if event is protected and if client is not authenticated - if (namespace.events[event_names[index]].protected === true && - namespace.clients.get(socket_id)["_authenticated"] === false) + if ( + namespace.events[event_names[index]].protected === true && + namespace.clients.get(socket_id)["_authenticated"] === false + ) { return { jsonrpc: "2.0", - error: utils.createError(-32606), - id: message.id || null + error: createError(-32606), + id: message.id || null, } } - const socket_index = namespace.events[event_names[index]].sockets.indexOf(socket_id) + const socket_index = + namespace.events[event_names[index]].sockets.indexOf(socket_id) if (socket_index >= 0) { results[name] = "socket has already been subscribed to event" @@ -627,7 +657,7 @@ export default class Server extends EventEmitter return { jsonrpc: "2.0", result: results, - id: message.id || null + id: message.id || null, } } else if (message.method === "rpc.off") @@ -635,8 +665,8 @@ export default class Server extends EventEmitter if (!message.params) return { jsonrpc: "2.0", - error: utils.createError(-32000), - id: message.id || null + error: createError(-32000), + id: message.id || null, } const results: IRPCResult = {} @@ -649,7 +679,8 @@ export default class Server extends EventEmitter continue } - const index = this.namespaces[ns].events[name].sockets.indexOf(socket_id) + const index = + this.namespaces[ns].events[name].sockets.indexOf(socket_id) if (index === -1) { @@ -664,7 +695,7 @@ export default class Server extends EventEmitter return { jsonrpc: "2.0", result: results, - id: message.id || null + id: message.id || null, } } else if (message.method === "rpc.login") @@ -672,8 +703,8 @@ export default class Server extends EventEmitter if (!message.params) return { jsonrpc: "2.0", - error: utils.createError(-32604), - id: message.id || null + error: createError(-32604), + id: message.id || null, } } @@ -681,34 +712,36 @@ export default class Server extends EventEmitter { return { jsonrpc: "2.0", - error: utils.createError(-32601), - id: message.id || null + error: createError(-32601), + id: message.id || null, } } let response = null // reject request if method is protected and if client is not authenticated - if (this.namespaces[ns].rpc_methods[message.method].protected === true && - this.namespaces[ns].clients.get(socket_id)["_authenticated"] === false) + if ( + this.namespaces[ns].rpc_methods[message.method].protected === true && + this.namespaces[ns].clients.get(socket_id)["_authenticated"] === false + ) { return { jsonrpc: "2.0", - error: utils.createError(-32605), - id: message.id || null + error: createError(-32605), + id: message.id || null, } } try { - response = await this.namespaces[ns].rpc_methods[message.method] - .fn(message.params, socket_id) + response = await this.namespaces[ns].rpc_methods[message.method].fn( + message.params, + socket_id + ) } - catch (error) { - if (!message.id) - return + if (!message.id) return if (error instanceof Error) return { @@ -716,21 +749,20 @@ export default class Server extends EventEmitter error: { code: -32000, message: error.name, - data: error.message + data: error.message, }, - id: message.id + id: message.id, } return { jsonrpc: "2.0", error: error, - id: message.id + id: message.id, } } // client sent a notification, so we won't need a reply - if (!message.id) - return + if (!message.id) return // if login middleware returned true, set connection as authenticated if (message.method === "rpc.login" && response === true) @@ -743,28 +775,58 @@ export default class Server extends EventEmitter return { jsonrpc: "2.0", result: response, - id: message.id + id: message.id, } } /** - * Generate a new namespace store. - * Also preregister some special namespace methods. - * @private - * @param {String} name - namespaces identifier - * @return {undefined} - */ + * Generate a new namespace store. + * Also preregister some special namespace methods. + * @private + * @param {String} name - namespaces identifier + * @return {undefined} + */ private _generateNamespace(name: string) { this.namespaces[name] = { rpc_methods: { - "__listMethods": { + __listMethods: { fn: () => Object.keys(this.namespaces[name].rpc_methods), - protected: false - } + protected: false, + }, }, clients: new Map(), - events: {} + events: {}, } } } + +const RPC_ERRORS = new Map([ + [-32000, "Event not provided"], + [-32600, "Invalid Request"], + [-32601, "Method not found"], + [-32602, "Invalid params"], + [-32603, "Internal error"], + [-32604, "Params not found"], + [-32605, "Method forbidden"], + [-32606, "Event forbidden"], + [-32700, "Parse error"], +]) + +/** + * Creates a JSON-RPC 2.0-compliant error. + * @param {Number} code - error code + * @param {String} details - error details + * @return {Object} + */ +export function createError(code: number, details?: string) +{ + const error: IRPCError = { + code: code, + message: RPC_ERRORS.get(code) || "Internal Server Error", + } + + if (details) error["data"] = details + + return error +} diff --git a/src/lib/utils.cts b/src/lib/utils.cts deleted file mode 100644 index cf351dd..0000000 --- a/src/lib/utils.cts +++ /dev/null @@ -1,58 +0,0 @@ -"use strict" - -const errors = new Map([ - [-32000, "Event not provided"], - [-32600, "Invalid Request"], - [-32601, "Method not found"], - [-32602, "Invalid params"], - [-32603, "Internal error"], - [-32604, "Params not found"], - [-32605, "Method forbidden"], - [-32606, "Event forbidden"], - [-32700, "Parse error"] -]) - -interface IRPCError { - code: number; - message: string; - data?: string; -} - -export interface DataPack { - encode(value: T): R; - decode(value: R): T; -} - -export class DefaultDataPack implements DataPack -{ - encode(value: Object): string - { - return JSON.stringify(value) - } - - decode(value: string): Object - { - return JSON.parse(value) - } -} - -/** - * Creates a JSON-RPC 2.0-compliant error. - * @param {Number} code - error code - * @param {String} details - error details - * @return {Object} - */ -function createError(code: number, details?: string) -{ - const error: IRPCError = { - code: code, - message: errors.get(code) || "Internal Server Error" - } - - if (details) - error["data"] = details - - return error -} - -export { createError } diff --git a/src/lib/utils.ts b/src/lib/utils.ts new file mode 100644 index 0000000..e67c9a9 --- /dev/null +++ b/src/lib/utils.ts @@ -0,0 +1,22 @@ +"use strict" + +export interface DataPack< + T, + R extends string | ArrayBufferLike | Blob | ArrayBufferView +> { + encode(value: T): R; + decode(value: R): T; +} + +export class DefaultDataPack implements DataPack +{ + encode(value: Object): string + { + return JSON.stringify(value) + } + + decode(value: string): Object + { + return JSON.parse(value) + } +} diff --git a/tsconfig.json b/tsconfig.json index 85b59e2..000b37b 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,15 +1,14 @@ { "compilerOptions": { - "outDir": "./dist", - "declaration": true, + "allowJs": true, + "allowSyntheticDefaultImports": true, "allowUnreachableCode": false, - "noImplicitAny": true, - "module": "CommonJS", - "target": "ESNext", "esModuleInterop": true, + "module": "CommonJS", "moduleResolution": "node", - "allowSyntheticDefaultImports": true, - "allowJs": true + "noEmit": true, + "noImplicitAny": true, + "target": "ESNext", }, "include": [ "./src/**/*" diff --git a/tsup.config.ts b/tsup.config.ts new file mode 100644 index 0000000..4cfbaa2 --- /dev/null +++ b/tsup.config.ts @@ -0,0 +1,62 @@ +import { polyfillNode } from "esbuild-plugin-polyfill-node" +import { rename } from "node:fs/promises" +import { join } from "node:path" +import { defineConfig, Options } from "tsup" + +const BASE_OPTIONS: Options = { + clean: true, + dts: true, + outExtension: ({ format }) => + format === "iife" + ? {} + : { + js: `.${format === "cjs" ? "cjs" : "mjs"}`, + }, + sourcemap: true, + splitting: false, + treeshake: true, +} + +const BROWSER_OPTIONS: Options = { + esbuildPlugins: [ + polyfillNode({ + globals: { + buffer: true, + }, + polyfills: { + buffer: true, + }, + }), + ], +} + +export default defineConfig([ + { + ...BASE_OPTIONS, + ...BROWSER_OPTIONS, + entry: ["src/index.browser.ts"], + format: ["cjs", "esm"], + name: "Browser", + }, + { + ...BASE_OPTIONS, + ...BROWSER_OPTIONS, + dts: false, + entry: ["src/index.browser-bundle.ts"], + format: "iife", + globalName: "RPCWebsocket", + name: "Browser Bundle", + minify: true, + outExtension: () => ({ + js: ".js", + }), + sourcemap: false, + target: "es2017", + }, + { + ...BASE_OPTIONS, + entry: ["src/index.ts"], + format: ["cjs", "esm"], + name: "Node", + }, +])