@wxn0brp/gloves-link-client 0.0.14 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +1 -1
- package/dist/GlovesLinkClient.js +1 -1
- package/dist/GlovesLinkClient.js.map +3 -3
- package/dist/index.d.ts +15 -8
- package/dist/index.js +54 -42
- package/package.json +2 -2
package/LICENSE
CHANGED
package/dist/GlovesLinkClient.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
var
|
|
1
|
+
var h=class{_events={};on(e,t){let s=e;this._events[s]||(this._events[s]=[]),this._events[s].push(t)}once(e,t){let s=(...o)=>{this.off(e,s),t(...o)};this.on(e,s)}off(e,t){let s=e;this._events[s]&&(this._events[s]=this._events[s].filter(o=>o!==t))}_emit(e,...t){let s=this._events[e];s?.length&&s.forEach(o=>o(...t))}emit(e,...t){this._emit(e,...t),this._emit("*",e,...t)}listenerCount(e){return this._events[e]?.length||0}},u=h;var d=class{_ws;_ackIdCounter;_ackCallbacks;_handlers=new u;_manuallyDisconnected=!1;_messageQueue=[];_reconnectAttempts=0;opts;url;connected=!1;constructor(e,t={}){this._ackIdCounter=1,this._ackCallbacks=new Map,this.opts={logs:!1,token:null,autoConnect:!0,statusPath:"/gloves-link/status",reConnect:!0,reConnectInterval:1e3,maxReConnectAttempts:5,reConnectBackoffFactor:2,maxReConnectDelay:15e3,...t},this.url=new URL(e,typeof window<"u"?window.location.href.replace("http","ws"):"ws://localhost"),this.opts.token&&this.url.searchParams.set("token",this.opts.token),this.opts.autoConnect&&this.connect()}connect(){this._manuallyDisconnected=!1;let e=Date.now().toString(36)+Math.random().toString(36).substring(2,10);this.url.searchParams.set("id",e),this.opts.connectionData&&this.url.searchParams.set("data",JSON.stringify(this.opts.connectionData)),this._ws=new WebSocket(this.url.href),this._ws.onopen=()=>{this.connected=!0,this._reconnectAttempts=0,this.opts.logs&&console.log("[ws] Connected");let t;for(;t=this._messageQueue.shift();)this._ws.send(t);this._handlersEmit("connect")},this._ws.onerror=(...t)=>{this.opts.logs&&console.warn("[ws] Error:",t),this._handlersEmit("error",...t)},this._ws.onmessage=t=>{let s=t?.data?.toString()||t?.toString()||"",o;try{o=JSON.parse(s)}catch{this.opts.logs&&console.warn("[ws] Invalid JSON:",s);return}if("ack"in o){let c=o.ack,l=this._ackCallbacks.get(c);l&&(this._ackCallbacks.delete(c),l(...o.data));return}let{evt:a,data:n,ackI:i}=o;if(!(!a||n&&!Array.isArray(n))){if(Array.isArray(i))for(let c=0;c<i.length;c++){let l=i[c];if(!n[l])break;let m=n[l];n[l]=(...p)=>{this._ws.send(JSON.stringify({ack:m,data:p}))}}this._handlersEmit(a,...n)}},this._ws.onclose=async t=>{if(this.connected=!1,this.opts.logs&&console.log("[ws] Disconnected",t),this._handlersEmit("disconnect",t),this._manuallyDisconnected||!this.opts.reConnect)return;if(t.code===1006){this.opts.logs&&console.log("[ws] Connection closed by server");try{if(!await f(this,e))return}catch(n){this.opts.logs&&console.error("[ws] Status error",n)}}if(this._reconnectAttempts++,this._reconnectAttempts>this.opts.maxReConnectAttempts){this.opts.logs&&console.error(`[ws] Max reconnect attempts reached (${this.opts.maxReConnectAttempts})`),this._handlersEmit("reconnect_failed");return}let s=Math.min(this.opts.reConnectInterval*this.opts.reConnectBackoffFactor**(this._reconnectAttempts-1),this.opts.maxReConnectDelay),o=1+Math.random()*.5,a=Math.max(s*o,this.opts.reConnectInterval);this.opts.logs&&console.log(`[ws] Reconnecting in ${a.toFixed(0)}ms (attempt ${this._reconnectAttempts})`),setTimeout(()=>{this.connect()},a)}}on(e,t){this._handlers.on(e,t)}once(e,t){this._handlers.once(e,t)}emit(e,...t){let s=t.map((a,n)=>{if(typeof a=="function")return n}).filter(a=>a!==void 0);for(let a=0;a<s.length;a++){let n=s[a],i=this._ackIdCounter++;this._ackCallbacks.set(i,t[n]),t[n]=i}let o=JSON.stringify({evt:e,data:t||void 0,ackI:s.length?s:void 0});this.connected&&this._ws?.readyState===WebSocket.OPEN?this._ws.send(o):this._messageQueue.push(o)}send(e,...t){return this.emit(e,...t)}disconnect(){this._manuallyDisconnected=!0,this._ws.close()}close(){this._ws.close()}_handlersEmit(e,...t){this._handlers.emit(e,...t)}};async function f(r,e){let t=new URL(r.opts.statusPath,r.url.origin);t.searchParams.set("id",e),t.searchParams.set("path",r.url.pathname);let s=t.toString().replace("ws","http"),o=await fetch(s);if(!o.ok)return console.error("[ws] Status error",o.status),!0;let a=await o.json();if(a.err)return r.opts.logs&&console.log("[ws] Status error",a.msg),!0;let n=a.status;return r.opts.logs&&console.log("[ws] Status",n),n.status===401?(r._handlersEmit("connect_unauthorized",n.msg),!1):n.status===403?(r._handlersEmit("connect_forbidden",n.msg),!1):n.status===500?(r._handlersEmit("connect_serverError",n.msg),!1):!0}export{d as GLC,d as GlovesLinkClient,d as client,d as default};
|
|
2
2
|
//# sourceMappingURL=GlovesLinkClient.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../node_modules/@wxn0brp/event-emitter/dist/index.js", "../src/index.ts"],
|
|
4
|
-
"sourcesContent": ["export class VEE {\n _events = {};\n /**\n * Registers an event listener\n * @param {K} event - event name\n * @param {Function} listener - function to be called when event occurs\n */\n on(event, listener) {\n const _event = event;\n if (!this._events[_event])\n this._events[_event] = [];\n this._events[_event].push(listener);\n }\n /**\n * Registers a one-time event listener\n * @param {K} event - event name\n * @param {Function} listener - function to be called once\n */\n once(event, listener) {\n const onceListener = (...args) => {\n this.off(event, onceListener);\n listener(...args);\n };\n this.on(event, onceListener);\n }\n /**\n * Removes an event listener.\n * @param {K} event - event name\n * @param {Function} listener - listener to remove\n */\n off(event, listener) {\n const _event = event;\n if (!this._events[_event])\n return;\n this._events[_event] = this._events[_event].filter(l => l !== listener);\n }\n /**\n * Emits an event\n * @param {K} event - event name\n * @param {...EventArgs<T, K>} args - arguments to be passed to listeners\n */\n emit(event, ...args) {\n const listeners = this._events[event];\n if (listeners && listeners.length > 0) {\n listeners.forEach(listener => {\n listener(...args);\n });\n }\n }\n /**\n * Returns the number of listeners for the given event\n * @param {K} event - event name\n */\n listenerCount(event) {\n return this._events[event]?.length || 0;\n }\n}\nexport default VEE;\nexport { VEE as EventEmitter };\n", "import VEE, { EventArgs, EventMap, EventName } from \"@wxn0brp/event-emitter\";\n\nexport interface GLC_Opts {\n reConnect: boolean,\n reConnectInterval: number,\n logs: boolean;\n token: string;\n autoConnect: boolean;\n connectionData?: Record<string, any>;\n}\n\nexport interface GLC_DataEvent {\n evt: string;\n data: any[];\n ackI?: number[];\n}\n\nexport interface GLC_AckEvent {\n ack: number;\n data: any[];\n}\n\nexport type InternalEvents = {\n connect: (ws: WebSocket) => void;\n error: (...err: any[]) => void;\n disconnect: (event: CloseEvent) => void;\n connect_unauthorized: (msg: string) => void;\n connect_forbidden: (msg: string) => void;\n connect_serverError: (msg: string) => void;\n}\n\nexport class GlovesLinkClient<InputEvents extends EventMap = {}, OutputEvents extends EventMap = {}> {\n public ws: WebSocket;\n public ackIdCounter: number;\n public ackCallbacks: Map<number, Function>;\n public handlers = new VEE<InputEvents>();\n public opts: GLC_Opts;\n public url: URL;\n public connected: boolean = false;\n private _manuallyDisconnected: boolean = false;\n private messageQueue: string[] = [];\n\n constructor(url: string, opts: Partial<GLC_Opts> = {}) {\n this.ackIdCounter = 1;\n this.ackCallbacks = new Map();\n this.opts = {\n logs: false,\n reConnect: true,\n reConnectInterval: 1000,\n token: null,\n autoConnect: true,\n ...opts\n }\n\n this.url = new URL(url, typeof window !== \"undefined\" ? window.location.href.replace(\"http\", \"ws\") : \"ws://localhost\");\n if (this.opts.token) this.url.searchParams.set(\"token\", this.opts.token);\n\n if (this.opts.autoConnect) this.connect();\n }\n\n connect() {\n this._manuallyDisconnected = false;\n const id = Date.now().toString(36) + Math.random().toString(36).substring(2, 10);\n this.url.searchParams.set(\"id\", id);\n\n if (this.opts.connectionData)\n this.url.searchParams.set(\"data\", JSON.stringify(this.opts.connectionData));\n\n this.ws = new WebSocket(this.url.href);\n\n this.ws.onopen = () => {\n this.connected = true;\n if (this.opts.logs) console.log(\"[ws] Connected\");\n\n let msg: string;\n while (msg = this.messageQueue.shift()) {\n this.ws.send(msg);\n }\n\n this._handlersEmit(\"connect\");\n }\n\n this.ws.onerror = (...err: any) => {\n if (this.opts.logs) console.warn(\"[ws] Error:\", err);\n this._handlersEmit(\"error\", ...err);\n }\n\n this.ws.onmessage = (_data) => {\n const raw = _data?.data?.toString() || _data?.toString() || \"\";\n let msg: GLC_DataEvent | GLC_AckEvent;\n\n try {\n msg = JSON.parse(raw);\n } catch {\n if (this.opts.logs) console.warn(\"[ws] Invalid JSON:\", raw);\n return;\n }\n\n if (\"ack\" in msg) {\n const ackId = msg.ack;\n const ackCallback = this.ackCallbacks.get(ackId);\n if (ackCallback) {\n this.ackCallbacks.delete(ackId);\n ackCallback(...msg.data);\n }\n return;\n }\n\n const { evt, data, ackI } = msg;\n if (!evt || (data && !Array.isArray(data))) return;\n\n if (Array.isArray(ackI)) {\n for (let i = 0; i < ackI.length; i++) {\n const ackIndex = ackI[i];\n if (!data[ackIndex]) break;\n\n const ackId = data[ackIndex];\n data[ackIndex] = (...res: any) => {\n this.ws.send(JSON.stringify({\n ack: ackId,\n data: res\n }));\n };\n }\n }\n\n this._handlersEmit(evt, ...data);\n }\n\n this.ws.onclose = async (event: CloseEvent) => {\n this.connected = false;\n if (this.opts.logs) console.log(\"[ws] Disconnected\", event);\n this._handlersEmit(\"disconnect\", event);\n\n if (this._manuallyDisconnected) {\n this._manuallyDisconnected = false;\n return;\n }\n\n if (event.code === 1006) {\n if (this.opts.logs) console.log(\"[ws] Connection closed by server\");\n\n try {\n const canReconnect = await checkStatus(this, id);\n if (!canReconnect) return;\n } catch (e) {\n if (this.opts.logs)\n console.error(\"[ws] Status error\", e);\n }\n }\n\n if (!this.opts.reConnect) return;\n\n setTimeout(() => {\n this.connect();\n }, this.opts.reConnectInterval);\n }\n }\n\n on<K extends EventName<InputEvents & InternalEvents>>(event: K, listener: (InputEvents & InternalEvents)[K]) {\n this.handlers.on(event, listener as any);\n }\n\n once<K extends EventName<InputEvents & InternalEvents>>(event: K, listener: (InputEvents & InternalEvents)[K]) {\n this.handlers.once(event, listener as any);\n }\n\n emit<K extends EventName<OutputEvents>>(evt: K, ...args: EventArgs<OutputEvents, K>) {\n const ackI = args.map((data, i) => {\n if (typeof data === \"function\") return i;\n }).filter(i => i !== undefined);\n\n for (let i = 0; i < ackI.length; i++) {\n const ackIndex = ackI[i];\n const ackId = this.ackIdCounter++;\n this.ackCallbacks.set(ackId, args[ackIndex]);\n args[ackIndex] = ackId;\n }\n\n const payload = JSON.stringify({\n evt,\n data: args || undefined,\n ackI: ackI.length ? ackI : undefined\n });\n\n if (this.connected && this.ws?.readyState === WebSocket.OPEN)\n this.ws.send(payload);\n else\n this.messageQueue.push(payload);\n }\n\n send<K extends EventName<OutputEvents>>(evt: K, ...args: EventArgs<OutputEvents, K>) {\n return this.emit(evt, ...args);\n }\n\n disconnect() {\n this._manuallyDisconnected = true;\n this.ws.close();\n }\n\n close() {\n this.ws.close();\n }\n\n _handlersEmit(evtName: string, ...args: any[]) {\n // @ts-ignore\n this.handlers.emit(evtName, ...args);\n // @ts-ignore\n this.handlers.emit(\"*\", evtName, ...args);\n }\n}\n\nasync function checkStatus(client: GlovesLinkClient, id: string) {\n const params = new URLSearchParams();\n params.set(\"id\", id);\n params.set(\"path\", client.url.pathname);\n\n const statusUrl = client.url.origin + \"/gloves-link/status?\" + params.toString();\n const res = await fetch(statusUrl.replace(\"ws\", \"http\"));\n if (!res.ok) {\n console.error(\"[ws] Status error\", res.status);\n return true;\n }\n\n const data = await res.json();\n if (data.err) {\n if (client.opts.logs) console.log(\"[ws] Status error\", data.msg);\n return true;\n }\n\n const status = data.status as { status: number, msg?: string };\n if (client.opts.logs) console.log(\"[ws] Status\", status);\n\n if (status.status === 401) {\n client._handlersEmit(\"connect_unauthorized\", status.msg);\n return false;\n }\n else if (status.status === 403) {\n client._handlersEmit(\"connect_forbidden\", status.msg);\n return false;\n }\n else if (status.status === 500) {\n client._handlersEmit(\"connect_serverError\", status.msg);\n return false;\n }\n\n return true;\n}\n\nexport {\n GlovesLinkClient as default,\n GlovesLinkClient as GLC,\n GlovesLinkClient as client,\n}"],
|
|
5
|
-
"mappings": "AAAO,IAAMA,EAAN,KAAU,CACb,QAAU,CAAC,EAMX,GAAGC,EAAOC,EAAU,CAChB,IAAMC,EAASF,EACV,KAAK,QAAQE,CAAM,IACpB,KAAK,QAAQA,CAAM,EAAI,CAAC,GAC5B,KAAK,QAAQA,CAAM,EAAE,KAAKD,CAAQ,CACtC,CAMA,KAAKD,EAAOC,EAAU,CAClB,IAAME,EAAe,IAAIC,IAAS,CAC9B,KAAK,IAAIJ,EAAOG,CAAY,EAC5BF,EAAS,GAAGG,CAAI,CACpB,EACA,KAAK,GAAGJ,EAAOG,CAAY,CAC/B,CAMA,IAAIH,EAAOC,EAAU,CACjB,IAAMC,EAASF,EACV,KAAK,QAAQE,CAAM,IAExB,KAAK,QAAQA,CAAM,EAAI,KAAK,QAAQA,CAAM,EAAE,OAAOG,GAAKA,IAAMJ,CAAQ,EAC1E,
|
|
6
|
-
"names": ["VEE", "event", "listener", "_event", "onceListener", "args", "l", "listeners", "dist_default", "GlovesLinkClient", "dist_default", "url", "opts", "id", "msg", "err", "_data", "raw", "ackId", "ackCallback", "evt", "data", "ackI", "i", "ackIndex", "res", "event", "checkStatus", "e", "listener", "args", "payload", "evtName", "client", "
|
|
4
|
+
"sourcesContent": ["export class VEE {\n _events = {};\n /**\n * Registers an event listener\n * @param {K} event - event name\n * @param {Function} listener - function to be called when event occurs\n */\n on(event, listener) {\n const _event = event;\n if (!this._events[_event])\n this._events[_event] = [];\n this._events[_event].push(listener);\n }\n /**\n * Registers a one-time event listener\n * @param {K} event - event name\n * @param {Function} listener - function to be called once\n */\n once(event, listener) {\n const onceListener = (...args) => {\n this.off(event, onceListener);\n listener(...args);\n };\n this.on(event, onceListener);\n }\n /**\n * Removes an event listener.\n * @param {K} event - event name\n * @param {Function} listener - listener to remove\n */\n off(event, listener) {\n const _event = event;\n if (!this._events[_event])\n return;\n this._events[_event] = this._events[_event].filter(l => l !== listener);\n }\n _emit(event, ...args) {\n const listeners = this._events[event];\n if (!listeners?.length)\n return;\n listeners.forEach(listener => listener(...args));\n }\n /**\n * Emits an event\n * @param {K} event - event name\n * @param {...EventArgs<T, K>} args - arguments to be passed to listeners\n */\n emit(event, ...args) {\n this._emit(event, ...args);\n this._emit(\"*\", event, ...args);\n }\n /**\n * Returns the number of listeners for the given event\n * @param {K} event - event name\n */\n listenerCount(event) {\n return this._events[event]?.length || 0;\n }\n}\nexport default VEE;\nexport { VEE as EventEmitter };\n", "import VEE, { EventArgs, EventMap, EventName } from \"@wxn0brp/event-emitter\";\n\nexport interface GLC_Opts {\n logs: boolean;\n token: string;\n autoConnect: boolean;\n connectionData?: Record<string, any>;\n statusPath: string;\n reConnect: boolean,\n reConnectInterval: number,\n reConnectBackoffFactor: number;\n maxReConnectAttempts: number;\n /** Note: without jitter */\n maxReConnectDelay: number;\n}\n\nexport interface GLC_DataEvent {\n evt: string;\n data: any[];\n ackI?: number[];\n}\n\nexport interface GLC_AckEvent {\n ack: number;\n data: any[];\n}\n\nexport type InternalEvents = {\n connect: (ws: WebSocket) => void;\n error: (...err: any[]) => void;\n disconnect: (event: CloseEvent) => void;\n connect_unauthorized: (msg: string) => void;\n connect_forbidden: (msg: string) => void;\n connect_serverError: (msg: string) => void;\n reconnect_failed: () => void;\n}\n\nexport class GlovesLinkClient<InputEvents extends EventMap = {}, OutputEvents extends EventMap = {}> {\n _ws: WebSocket;\n _ackIdCounter: number;\n _ackCallbacks: Map<number, Function>;\n _handlers = new VEE<InputEvents>();\n _manuallyDisconnected: boolean = false;\n _messageQueue: string[] = [];\n _reconnectAttempts: number = 0;\n\n opts: GLC_Opts;\n url: URL;\n connected: boolean = false;\n\n constructor(url: string, opts: Partial<GLC_Opts> = {}) {\n this._ackIdCounter = 1;\n this._ackCallbacks = new Map();\n this.opts = {\n logs: false,\n token: null,\n autoConnect: true,\n statusPath: \"/gloves-link/status\",\n reConnect: true,\n reConnectInterval: 1000,\n maxReConnectAttempts: 5,\n reConnectBackoffFactor: 2,\n maxReConnectDelay: 15_000,\n ...opts\n }\n\n this.url = new URL(url, typeof window !== \"undefined\" ? window.location.href.replace(\"http\", \"ws\") : \"ws://localhost\");\n if (this.opts.token) this.url.searchParams.set(\"token\", this.opts.token);\n\n if (this.opts.autoConnect) this.connect();\n }\n\n connect() {\n this._manuallyDisconnected = false;\n const id = Date.now().toString(36) + Math.random().toString(36).substring(2, 10);\n this.url.searchParams.set(\"id\", id);\n\n if (this.opts.connectionData)\n this.url.searchParams.set(\"data\", JSON.stringify(this.opts.connectionData));\n\n this._ws = new WebSocket(this.url.href);\n\n this._ws.onopen = () => {\n this.connected = true;\n this._reconnectAttempts = 0;\n if (this.opts.logs) console.log(\"[ws] Connected\");\n\n let msg: string;\n while (msg = this._messageQueue.shift()) {\n this._ws.send(msg);\n }\n\n this._handlersEmit(\"connect\");\n }\n\n this._ws.onerror = (...err: any) => {\n if (this.opts.logs) console.warn(\"[ws] Error:\", err);\n this._handlersEmit(\"error\", ...err);\n }\n\n this._ws.onmessage = (_data) => {\n const raw = _data?.data?.toString() || _data?.toString() || \"\";\n let msg: GLC_DataEvent | GLC_AckEvent;\n\n try {\n msg = JSON.parse(raw);\n } catch {\n if (this.opts.logs) console.warn(\"[ws] Invalid JSON:\", raw);\n return;\n }\n\n if (\"ack\" in msg) {\n const ackId = msg.ack;\n const ackCallback = this._ackCallbacks.get(ackId);\n if (ackCallback) {\n this._ackCallbacks.delete(ackId);\n ackCallback(...msg.data);\n }\n return;\n }\n\n const { evt, data, ackI } = msg;\n if (!evt || (data && !Array.isArray(data))) return;\n\n if (Array.isArray(ackI)) {\n for (let i = 0; i < ackI.length; i++) {\n const ackIndex = ackI[i];\n if (!data[ackIndex]) break;\n\n const ackId = data[ackIndex];\n data[ackIndex] = (...res: any) => {\n this._ws.send(JSON.stringify({\n ack: ackId,\n data: res\n }));\n };\n }\n }\n\n this._handlersEmit(evt, ...data);\n }\n\n this._ws.onclose = async (event: CloseEvent) => {\n this.connected = false;\n if (this.opts.logs) console.log(\"[ws] Disconnected\", event);\n this._handlersEmit(\"disconnect\", event);\n\n if (this._manuallyDisconnected || !this.opts.reConnect) return;\n\n if (event.code === 1006) {\n if (this.opts.logs) console.log(\"[ws] Connection closed by server\");\n\n try {\n const canReconnect = await checkStatus(this, id);\n if (!canReconnect) return;\n } catch (e) {\n if (this.opts.logs)\n console.error(\"[ws] Status error\", e);\n }\n }\n\n this._reconnectAttempts++;\n\n if (this._reconnectAttempts > this.opts.maxReConnectAttempts) {\n if (this.opts.logs)\n console.error(`[ws] Max reconnect attempts reached (${this.opts.maxReConnectAttempts})`);\n\n this._handlersEmit(\"reconnect_failed\");\n return;\n }\n\n const expDelay = Math.min(\n this.opts.reConnectInterval * this.opts.reConnectBackoffFactor ** (this._reconnectAttempts - 1),\n this.opts.maxReConnectDelay\n );\n\n const jitter = 1 + Math.random() * 0.5;\n const delay = Math.max(\n expDelay * jitter,\n this.opts.reConnectInterval\n );\n\n if (this.opts.logs)\n console.log(\n `[ws] Reconnecting in ${delay.toFixed(0)}ms (attempt ${this._reconnectAttempts})`\n );\n\n setTimeout(() => {\n this.connect();\n }, delay);\n }\n }\n\n on<K extends EventName<InputEvents & InternalEvents>>(event: K, listener: (InputEvents & InternalEvents)[K]) {\n this._handlers.on(event, listener as any);\n }\n\n once<K extends EventName<InputEvents & InternalEvents>>(event: K, listener: (InputEvents & InternalEvents)[K]) {\n this._handlers.once(event, listener as any);\n }\n\n emit<K extends EventName<OutputEvents>>(evt: K, ...args: EventArgs<OutputEvents, K>) {\n const ackI = args.map((data, i) => {\n if (typeof data === \"function\") return i;\n }).filter(i => i !== undefined);\n\n for (let i = 0; i < ackI.length; i++) {\n const ackIndex = ackI[i];\n const ackId = this._ackIdCounter++;\n this._ackCallbacks.set(ackId, args[ackIndex]);\n args[ackIndex] = ackId;\n }\n\n const payload = JSON.stringify({\n evt,\n data: args || undefined,\n ackI: ackI.length ? ackI : undefined\n });\n\n if (this.connected && this._ws?.readyState === WebSocket.OPEN)\n this._ws.send(payload);\n else\n this._messageQueue.push(payload);\n }\n\n send<K extends EventName<OutputEvents>>(evt: K, ...args: EventArgs<OutputEvents, K>) {\n return this.emit(evt, ...args);\n }\n\n disconnect() {\n this._manuallyDisconnected = true;\n this._ws.close();\n }\n\n close() {\n this._ws.close();\n }\n\n _handlersEmit(evtName: string, ...args: any[]) {\n // @ts-ignore\n this._handlers.emit(evtName, ...args);\n }\n}\n\nasync function checkStatus(client: GlovesLinkClient, id: string) {\n const statusURL = new URL(client.opts.statusPath, client.url.origin);\n statusURL.searchParams.set(\"id\", id);\n statusURL.searchParams.set(\"path\", client.url.pathname);\n\n const statusUrl = statusURL.toString().replace(\"ws\", \"http\");\n\n const res = await fetch(statusUrl);\n if (!res.ok) {\n console.error(\"[ws] Status error\", res.status);\n return true;\n }\n\n const data = await res.json();\n if (data.err) {\n if (client.opts.logs) console.log(\"[ws] Status error\", data.msg);\n return true;\n }\n\n const status = data.status as { status: number, msg?: string };\n if (client.opts.logs) console.log(\"[ws] Status\", status);\n\n if (status.status === 401) {\n client._handlersEmit(\"connect_unauthorized\", status.msg);\n return false;\n }\n else if (status.status === 403) {\n client._handlersEmit(\"connect_forbidden\", status.msg);\n return false;\n }\n else if (status.status === 500) {\n client._handlersEmit(\"connect_serverError\", status.msg);\n return false;\n }\n\n return true;\n}\n\nexport {\n GlovesLinkClient as default,\n GlovesLinkClient as GLC,\n GlovesLinkClient as client,\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["VEE", "event", "listener", "_event", "onceListener", "args", "l", "listeners", "dist_default", "GlovesLinkClient", "dist_default", "url", "opts", "id", "msg", "err", "_data", "raw", "ackId", "ackCallback", "evt", "data", "ackI", "i", "ackIndex", "res", "event", "checkStatus", "e", "expDelay", "jitter", "delay", "listener", "args", "payload", "evtName", "client", "statusURL", "statusUrl", "status"]
|
|
7
7
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,11 +1,16 @@
|
|
|
1
1
|
import VEE, { EventArgs, EventMap, EventName } from "@wxn0brp/event-emitter";
|
|
2
2
|
export interface GLC_Opts {
|
|
3
|
-
reConnect: boolean;
|
|
4
|
-
reConnectInterval: number;
|
|
5
3
|
logs: boolean;
|
|
6
4
|
token: string;
|
|
7
5
|
autoConnect: boolean;
|
|
8
6
|
connectionData?: Record<string, any>;
|
|
7
|
+
statusPath: string;
|
|
8
|
+
reConnect: boolean;
|
|
9
|
+
reConnectInterval: number;
|
|
10
|
+
reConnectBackoffFactor: number;
|
|
11
|
+
maxReConnectAttempts: number;
|
|
12
|
+
/** Note: without jitter */
|
|
13
|
+
maxReConnectDelay: number;
|
|
9
14
|
}
|
|
10
15
|
export interface GLC_DataEvent {
|
|
11
16
|
evt: string;
|
|
@@ -23,17 +28,19 @@ export type InternalEvents = {
|
|
|
23
28
|
connect_unauthorized: (msg: string) => void;
|
|
24
29
|
connect_forbidden: (msg: string) => void;
|
|
25
30
|
connect_serverError: (msg: string) => void;
|
|
31
|
+
reconnect_failed: () => void;
|
|
26
32
|
};
|
|
27
33
|
export declare class GlovesLinkClient<InputEvents extends EventMap = {}, OutputEvents extends EventMap = {}> {
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
34
|
+
_ws: WebSocket;
|
|
35
|
+
_ackIdCounter: number;
|
|
36
|
+
_ackCallbacks: Map<number, Function>;
|
|
37
|
+
_handlers: VEE<InputEvents>;
|
|
38
|
+
_manuallyDisconnected: boolean;
|
|
39
|
+
_messageQueue: string[];
|
|
40
|
+
_reconnectAttempts: number;
|
|
32
41
|
opts: GLC_Opts;
|
|
33
42
|
url: URL;
|
|
34
43
|
connected: boolean;
|
|
35
|
-
private _manuallyDisconnected;
|
|
36
|
-
private messageQueue;
|
|
37
44
|
constructor(url: string, opts?: Partial<GLC_Opts>);
|
|
38
45
|
connect(): void;
|
|
39
46
|
on<K extends EventName<InputEvents & InternalEvents>>(event: K, listener: (InputEvents & InternalEvents)[K]): void;
|
package/dist/index.js
CHANGED
|
@@ -1,23 +1,28 @@
|
|
|
1
1
|
import VEE from "@wxn0brp/event-emitter";
|
|
2
2
|
export class GlovesLinkClient {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
3
|
+
_ws;
|
|
4
|
+
_ackIdCounter;
|
|
5
|
+
_ackCallbacks;
|
|
6
|
+
_handlers = new VEE();
|
|
7
|
+
_manuallyDisconnected = false;
|
|
8
|
+
_messageQueue = [];
|
|
9
|
+
_reconnectAttempts = 0;
|
|
7
10
|
opts;
|
|
8
11
|
url;
|
|
9
12
|
connected = false;
|
|
10
|
-
_manuallyDisconnected = false;
|
|
11
|
-
messageQueue = [];
|
|
12
13
|
constructor(url, opts = {}) {
|
|
13
|
-
this.
|
|
14
|
-
this.
|
|
14
|
+
this._ackIdCounter = 1;
|
|
15
|
+
this._ackCallbacks = new Map();
|
|
15
16
|
this.opts = {
|
|
16
17
|
logs: false,
|
|
17
|
-
reConnect: true,
|
|
18
|
-
reConnectInterval: 1000,
|
|
19
18
|
token: null,
|
|
20
19
|
autoConnect: true,
|
|
20
|
+
statusPath: "/gloves-link/status",
|
|
21
|
+
reConnect: true,
|
|
22
|
+
reConnectInterval: 1000,
|
|
23
|
+
maxReConnectAttempts: 5,
|
|
24
|
+
reConnectBackoffFactor: 2,
|
|
25
|
+
maxReConnectDelay: 15_000,
|
|
21
26
|
...opts
|
|
22
27
|
};
|
|
23
28
|
this.url = new URL(url, typeof window !== "undefined" ? window.location.href.replace("http", "ws") : "ws://localhost");
|
|
@@ -32,23 +37,24 @@ export class GlovesLinkClient {
|
|
|
32
37
|
this.url.searchParams.set("id", id);
|
|
33
38
|
if (this.opts.connectionData)
|
|
34
39
|
this.url.searchParams.set("data", JSON.stringify(this.opts.connectionData));
|
|
35
|
-
this.
|
|
36
|
-
this.
|
|
40
|
+
this._ws = new WebSocket(this.url.href);
|
|
41
|
+
this._ws.onopen = () => {
|
|
37
42
|
this.connected = true;
|
|
43
|
+
this._reconnectAttempts = 0;
|
|
38
44
|
if (this.opts.logs)
|
|
39
45
|
console.log("[ws] Connected");
|
|
40
46
|
let msg;
|
|
41
|
-
while (msg = this.
|
|
42
|
-
this.
|
|
47
|
+
while (msg = this._messageQueue.shift()) {
|
|
48
|
+
this._ws.send(msg);
|
|
43
49
|
}
|
|
44
50
|
this._handlersEmit("connect");
|
|
45
51
|
};
|
|
46
|
-
this.
|
|
52
|
+
this._ws.onerror = (...err) => {
|
|
47
53
|
if (this.opts.logs)
|
|
48
54
|
console.warn("[ws] Error:", err);
|
|
49
55
|
this._handlersEmit("error", ...err);
|
|
50
56
|
};
|
|
51
|
-
this.
|
|
57
|
+
this._ws.onmessage = (_data) => {
|
|
52
58
|
const raw = _data?.data?.toString() || _data?.toString() || "";
|
|
53
59
|
let msg;
|
|
54
60
|
try {
|
|
@@ -61,9 +67,9 @@ export class GlovesLinkClient {
|
|
|
61
67
|
}
|
|
62
68
|
if ("ack" in msg) {
|
|
63
69
|
const ackId = msg.ack;
|
|
64
|
-
const ackCallback = this.
|
|
70
|
+
const ackCallback = this._ackCallbacks.get(ackId);
|
|
65
71
|
if (ackCallback) {
|
|
66
|
-
this.
|
|
72
|
+
this._ackCallbacks.delete(ackId);
|
|
67
73
|
ackCallback(...msg.data);
|
|
68
74
|
}
|
|
69
75
|
return;
|
|
@@ -78,7 +84,7 @@ export class GlovesLinkClient {
|
|
|
78
84
|
break;
|
|
79
85
|
const ackId = data[ackIndex];
|
|
80
86
|
data[ackIndex] = (...res) => {
|
|
81
|
-
this.
|
|
87
|
+
this._ws.send(JSON.stringify({
|
|
82
88
|
ack: ackId,
|
|
83
89
|
data: res
|
|
84
90
|
}));
|
|
@@ -87,15 +93,13 @@ export class GlovesLinkClient {
|
|
|
87
93
|
}
|
|
88
94
|
this._handlersEmit(evt, ...data);
|
|
89
95
|
};
|
|
90
|
-
this.
|
|
96
|
+
this._ws.onclose = async (event) => {
|
|
91
97
|
this.connected = false;
|
|
92
98
|
if (this.opts.logs)
|
|
93
99
|
console.log("[ws] Disconnected", event);
|
|
94
100
|
this._handlersEmit("disconnect", event);
|
|
95
|
-
if (this._manuallyDisconnected)
|
|
96
|
-
this._manuallyDisconnected = false;
|
|
101
|
+
if (this._manuallyDisconnected || !this.opts.reConnect)
|
|
97
102
|
return;
|
|
98
|
-
}
|
|
99
103
|
if (event.code === 1006) {
|
|
100
104
|
if (this.opts.logs)
|
|
101
105
|
console.log("[ws] Connection closed by server");
|
|
@@ -109,18 +113,28 @@ export class GlovesLinkClient {
|
|
|
109
113
|
console.error("[ws] Status error", e);
|
|
110
114
|
}
|
|
111
115
|
}
|
|
112
|
-
|
|
116
|
+
this._reconnectAttempts++;
|
|
117
|
+
if (this._reconnectAttempts > this.opts.maxReConnectAttempts) {
|
|
118
|
+
if (this.opts.logs)
|
|
119
|
+
console.error(`[ws] Max reconnect attempts reached (${this.opts.maxReConnectAttempts})`);
|
|
120
|
+
this._handlersEmit("reconnect_failed");
|
|
113
121
|
return;
|
|
122
|
+
}
|
|
123
|
+
const expDelay = Math.min(this.opts.reConnectInterval * this.opts.reConnectBackoffFactor ** (this._reconnectAttempts - 1), this.opts.maxReConnectDelay);
|
|
124
|
+
const jitter = 1 + Math.random() * 0.5;
|
|
125
|
+
const delay = Math.max(expDelay * jitter, this.opts.reConnectInterval);
|
|
126
|
+
if (this.opts.logs)
|
|
127
|
+
console.log(`[ws] Reconnecting in ${delay.toFixed(0)}ms (attempt ${this._reconnectAttempts})`);
|
|
114
128
|
setTimeout(() => {
|
|
115
129
|
this.connect();
|
|
116
|
-
},
|
|
130
|
+
}, delay);
|
|
117
131
|
};
|
|
118
132
|
}
|
|
119
133
|
on(event, listener) {
|
|
120
|
-
this.
|
|
134
|
+
this._handlers.on(event, listener);
|
|
121
135
|
}
|
|
122
136
|
once(event, listener) {
|
|
123
|
-
this.
|
|
137
|
+
this._handlers.once(event, listener);
|
|
124
138
|
}
|
|
125
139
|
emit(evt, ...args) {
|
|
126
140
|
const ackI = args.map((data, i) => {
|
|
@@ -129,8 +143,8 @@ export class GlovesLinkClient {
|
|
|
129
143
|
}).filter(i => i !== undefined);
|
|
130
144
|
for (let i = 0; i < ackI.length; i++) {
|
|
131
145
|
const ackIndex = ackI[i];
|
|
132
|
-
const ackId = this.
|
|
133
|
-
this.
|
|
146
|
+
const ackId = this._ackIdCounter++;
|
|
147
|
+
this._ackCallbacks.set(ackId, args[ackIndex]);
|
|
134
148
|
args[ackIndex] = ackId;
|
|
135
149
|
}
|
|
136
150
|
const payload = JSON.stringify({
|
|
@@ -138,34 +152,32 @@ export class GlovesLinkClient {
|
|
|
138
152
|
data: args || undefined,
|
|
139
153
|
ackI: ackI.length ? ackI : undefined
|
|
140
154
|
});
|
|
141
|
-
if (this.connected && this.
|
|
142
|
-
this.
|
|
155
|
+
if (this.connected && this._ws?.readyState === WebSocket.OPEN)
|
|
156
|
+
this._ws.send(payload);
|
|
143
157
|
else
|
|
144
|
-
this.
|
|
158
|
+
this._messageQueue.push(payload);
|
|
145
159
|
}
|
|
146
160
|
send(evt, ...args) {
|
|
147
161
|
return this.emit(evt, ...args);
|
|
148
162
|
}
|
|
149
163
|
disconnect() {
|
|
150
164
|
this._manuallyDisconnected = true;
|
|
151
|
-
this.
|
|
165
|
+
this._ws.close();
|
|
152
166
|
}
|
|
153
167
|
close() {
|
|
154
|
-
this.
|
|
168
|
+
this._ws.close();
|
|
155
169
|
}
|
|
156
170
|
_handlersEmit(evtName, ...args) {
|
|
157
171
|
// @ts-ignore
|
|
158
|
-
this.
|
|
159
|
-
// @ts-ignore
|
|
160
|
-
this.handlers.emit("*", evtName, ...args);
|
|
172
|
+
this._handlers.emit(evtName, ...args);
|
|
161
173
|
}
|
|
162
174
|
}
|
|
163
175
|
async function checkStatus(client, id) {
|
|
164
|
-
const
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
const statusUrl =
|
|
168
|
-
const res = await fetch(statusUrl
|
|
176
|
+
const statusURL = new URL(client.opts.statusPath, client.url.origin);
|
|
177
|
+
statusURL.searchParams.set("id", id);
|
|
178
|
+
statusURL.searchParams.set("path", client.url.pathname);
|
|
179
|
+
const statusUrl = statusURL.toString().replace("ws", "http");
|
|
180
|
+
const res = await fetch(statusUrl);
|
|
169
181
|
if (!res.ok) {
|
|
170
182
|
console.error("[ws] Status error", res.status);
|
|
171
183
|
return true;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wxn0brp/gloves-link-client",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.1.1",
|
|
4
4
|
"main": "dist/index.js",
|
|
5
5
|
"types": "dist/index.d.ts",
|
|
6
6
|
"author": "wxn0brP",
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
"typescript": "*"
|
|
19
19
|
},
|
|
20
20
|
"dependencies": {
|
|
21
|
-
"@wxn0brp/event-emitter": "
|
|
21
|
+
"@wxn0brp/event-emitter": "0.0.5"
|
|
22
22
|
},
|
|
23
23
|
"files": [
|
|
24
24
|
"dist"
|