web-mojo 2.1.46

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.
Files changed (91) hide show
  1. package/LICENSE +198 -0
  2. package/README.md +510 -0
  3. package/dist/admin.cjs.js +2 -0
  4. package/dist/admin.cjs.js.map +1 -0
  5. package/dist/admin.css +621 -0
  6. package/dist/admin.es.js +7973 -0
  7. package/dist/admin.es.js.map +1 -0
  8. package/dist/auth.cjs.js +2 -0
  9. package/dist/auth.cjs.js.map +1 -0
  10. package/dist/auth.css +804 -0
  11. package/dist/auth.es.js +2168 -0
  12. package/dist/auth.es.js.map +1 -0
  13. package/dist/charts.cjs.js +2 -0
  14. package/dist/charts.cjs.js.map +1 -0
  15. package/dist/charts.css +1002 -0
  16. package/dist/charts.es.js +16 -0
  17. package/dist/charts.es.js.map +1 -0
  18. package/dist/chunks/ContextMenu-BrHqj0fn.js +80 -0
  19. package/dist/chunks/ContextMenu-BrHqj0fn.js.map +1 -0
  20. package/dist/chunks/ContextMenu-gEcpSz56.js +2 -0
  21. package/dist/chunks/ContextMenu-gEcpSz56.js.map +1 -0
  22. package/dist/chunks/DataView-DPryYpEW.js +2 -0
  23. package/dist/chunks/DataView-DPryYpEW.js.map +1 -0
  24. package/dist/chunks/DataView-DjZQrpba.js +843 -0
  25. package/dist/chunks/DataView-DjZQrpba.js.map +1 -0
  26. package/dist/chunks/Dialog-BsRx4eg3.js +2 -0
  27. package/dist/chunks/Dialog-BsRx4eg3.js.map +1 -0
  28. package/dist/chunks/Dialog-DSlctbon.js +1377 -0
  29. package/dist/chunks/Dialog-DSlctbon.js.map +1 -0
  30. package/dist/chunks/FilePreviewView-BmFHzK5K.js +5868 -0
  31. package/dist/chunks/FilePreviewView-BmFHzK5K.js.map +1 -0
  32. package/dist/chunks/FilePreviewView-DcdRl_ta.js +2 -0
  33. package/dist/chunks/FilePreviewView-DcdRl_ta.js.map +1 -0
  34. package/dist/chunks/FormView-CmBuwKGD.js +2 -0
  35. package/dist/chunks/FormView-CmBuwKGD.js.map +1 -0
  36. package/dist/chunks/FormView-DqUBMPJ9.js +5054 -0
  37. package/dist/chunks/FormView-DqUBMPJ9.js.map +1 -0
  38. package/dist/chunks/MetricsChart-CM4CI6eA.js +2095 -0
  39. package/dist/chunks/MetricsChart-CM4CI6eA.js.map +1 -0
  40. package/dist/chunks/MetricsChart-CPidSMaN.js +2 -0
  41. package/dist/chunks/MetricsChart-CPidSMaN.js.map +1 -0
  42. package/dist/chunks/PDFViewer-BNQlnS83.js +2 -0
  43. package/dist/chunks/PDFViewer-BNQlnS83.js.map +1 -0
  44. package/dist/chunks/PDFViewer-Dyo-Oeyd.js +946 -0
  45. package/dist/chunks/PDFViewer-Dyo-Oeyd.js.map +1 -0
  46. package/dist/chunks/Page-B524zSQs.js +351 -0
  47. package/dist/chunks/Page-B524zSQs.js.map +1 -0
  48. package/dist/chunks/Page-BFgj0pAA.js +2 -0
  49. package/dist/chunks/Page-BFgj0pAA.js.map +1 -0
  50. package/dist/chunks/TokenManager-BXNva8Jk.js +287 -0
  51. package/dist/chunks/TokenManager-BXNva8Jk.js.map +1 -0
  52. package/dist/chunks/TokenManager-Bzn4guFm.js +2 -0
  53. package/dist/chunks/TokenManager-Bzn4guFm.js.map +1 -0
  54. package/dist/chunks/TopNav-D3I3_25f.js +371 -0
  55. package/dist/chunks/TopNav-D3I3_25f.js.map +1 -0
  56. package/dist/chunks/TopNav-MDjL4kV0.js +2 -0
  57. package/dist/chunks/TopNav-MDjL4kV0.js.map +1 -0
  58. package/dist/chunks/User-BalfYTEF.js +3 -0
  59. package/dist/chunks/User-BalfYTEF.js.map +1 -0
  60. package/dist/chunks/User-DwIT-CTQ.js +1937 -0
  61. package/dist/chunks/User-DwIT-CTQ.js.map +1 -0
  62. package/dist/chunks/WebApp-B6mgbNn2.js +4767 -0
  63. package/dist/chunks/WebApp-B6mgbNn2.js.map +1 -0
  64. package/dist/chunks/WebApp-DqDowtkl.js +2 -0
  65. package/dist/chunks/WebApp-DqDowtkl.js.map +1 -0
  66. package/dist/chunks/WebSocketClient-D6i85jl2.js +2 -0
  67. package/dist/chunks/WebSocketClient-D6i85jl2.js.map +1 -0
  68. package/dist/chunks/WebSocketClient-Dvl3AYx1.js +297 -0
  69. package/dist/chunks/WebSocketClient-Dvl3AYx1.js.map +1 -0
  70. package/dist/core.css +1181 -0
  71. package/dist/css/web-mojo.css +17 -0
  72. package/dist/css-manifest.json +6 -0
  73. package/dist/docit.cjs.js +2 -0
  74. package/dist/docit.cjs.js.map +1 -0
  75. package/dist/docit.es.js +959 -0
  76. package/dist/docit.es.js.map +1 -0
  77. package/dist/index.cjs.js +2 -0
  78. package/dist/index.cjs.js.map +1 -0
  79. package/dist/index.es.js +2681 -0
  80. package/dist/index.es.js.map +1 -0
  81. package/dist/lightbox.cjs.js +2 -0
  82. package/dist/lightbox.cjs.js.map +1 -0
  83. package/dist/lightbox.css +606 -0
  84. package/dist/lightbox.es.js +3737 -0
  85. package/dist/lightbox.es.js.map +1 -0
  86. package/dist/loader.es.js +115 -0
  87. package/dist/loader.umd.js +85 -0
  88. package/dist/portal.css +2446 -0
  89. package/dist/table.css +639 -0
  90. package/dist/toast.css +181 -0
  91. package/package.json +179 -0
@@ -0,0 +1,2 @@
1
+ "use strict";class WebSocketClient{constructor(e={}){this.url=e.url||null,this.protocols=e.protocols||[],this.socket=null,this.isConnected=!1,this.isConnecting=!1,this.shouldReconnect=!1!==e.autoReconnect,this.maxReconnectAttempts=e.maxReconnectAttempts||5,this.reconnectInterval=e.reconnectInterval||3e3,this.reconnectBackoff=e.reconnectBackoff||1.5,this.reconnectAttempts=0,this.reconnectTimer=null,this.pingInterval=e.pingInterval||3e4,this.pongTimeout=e.pongTimeout||5e3,this.pingTimer=null,this.pongTimer=null,this.eventBus=e.eventBus||null,this.listeners={},this.dataTransform=e.dataTransform||null,this.debug=e.debug||!1,this._onOpen=this._onOpen.bind(this),this._onMessage=this._onMessage.bind(this),this._onError=this._onError.bind(this),this._onClose=this._onClose.bind(this)}connect(e=null){if(e&&(this.url=e),!this.url)throw new Error("WebSocket URL is required");return this.isConnected||this.isConnecting?Promise.resolve():(this.isConnecting=!0,new Promise((e,t)=>{try{this.debug&&console.log("[WebSocket] Connecting to:",this.url),this.socket=new WebSocket(this.url,this.protocols),this.socket.addEventListener("open",this._onOpen),this.socket.addEventListener("message",this._onMessage),this.socket.addEventListener("error",this._onError),this.socket.addEventListener("close",this._onClose),this._connectResolve=e,this._connectReject=t}catch(n){this.isConnecting=!1,t(n)}}))}disconnect(){this.shouldReconnect=!1,this._clearTimers(),this.socket&&(this.debug&&console.log("[WebSocket] Disconnecting"),this.socket.close(1e3,"Client disconnecting"))}send(e){if(!this.isConnected||!this.socket)throw new Error("WebSocket is not connected");const t="string"==typeof e?e:JSON.stringify(e);this.socket.send(t),this.debug&&console.log("[WebSocket] Sent:",t)}on(e,t){this.listeners[e]||(this.listeners[e]=[]),this.listeners[e].push(t)}off(e,t){if(!this.listeners[e])return;if(!t)return void delete this.listeners[e];const n=this.listeners[e].indexOf(t);-1!==n&&this.listeners[e].splice(n,1)}emit(e,t){this.listeners[e]&&this.listeners[e].forEach(n=>{try{n(t)}catch(s){console.error(`[WebSocket] Error in ${e} listener:`,s)}}),this.eventBus&&"function"==typeof this.eventBus.emit&&this.eventBus.emit(`websocket:${e}`,{websocket:this,data:t})}getStatus(){return this.isConnected?"connected":this.isConnecting?"connecting":"disconnected"}getStats(){return{url:this.url,isConnected:this.isConnected,isConnecting:this.isConnecting,reconnectAttempts:this.reconnectAttempts,maxReconnectAttempts:this.maxReconnectAttempts,shouldReconnect:this.shouldReconnect}}_onOpen(e){this.debug&&console.log("[WebSocket] Connected"),this.isConnected=!0,this.isConnecting=!1,this.reconnectAttempts=0,this._startHeartbeat(),this._connectResolve&&(this._connectResolve(),this._connectResolve=null,this._connectReject=null),this.emit("connected",{url:this.url})}_onMessage(e){let t;this.debug&&console.log("[WebSocket] Received:",e.data);try{t=JSON.parse(e.data)}catch(n){t=e.data}if("pong"===t||t&&"pong"===t.type)this._clearPongTimeout();else{if(this.dataTransform&&"function"==typeof this.dataTransform)try{t=this.dataTransform(t)}catch(n){return console.error("[WebSocket] Error transforming data:",n),void this.emit("error",{error:n,originalData:t})}this.emit("message",t),this.emit("data",t)}}_onError(e){console.error("[WebSocket] Error:",e),this.emit("error",{error:e.error||new Error("WebSocket error"),event:e}),this._connectReject&&(this._connectReject(e.error||new Error("WebSocket connection failed")),this._connectResolve=null,this._connectReject=null)}_onClose(e){this.debug&&console.log("[WebSocket] Closed:",e.code,e.reason),this.isConnected=!1,this.isConnecting=!1,this._clearTimers(),this.socket&&(this.socket.removeEventListener("open",this._onOpen),this.socket.removeEventListener("message",this._onMessage),this.socket.removeEventListener("error",this._onError),this.socket.removeEventListener("close",this._onClose),this.socket=null),this.emit("disconnected",{code:e.code,reason:e.reason,wasClean:e.wasClean}),this.shouldReconnect&&1e3!==e.code&&this._attemptReconnect()}_attemptReconnect(){if(this.reconnectAttempts>=this.maxReconnectAttempts)return this.debug&&console.log("[WebSocket] Max reconnect attempts reached"),void this.emit("reconnect-failed",{attempts:this.reconnectAttempts,maxAttempts:this.maxReconnectAttempts});this.reconnectAttempts++;const e=this.reconnectInterval*Math.pow(this.reconnectBackoff,this.reconnectAttempts-1);this.debug&&console.log(`[WebSocket] Reconnecting in ${e}ms (attempt ${this.reconnectAttempts})`),this.emit("reconnecting",{attempt:this.reconnectAttempts,delay:e,maxAttempts:this.maxReconnectAttempts}),this.reconnectTimer=setTimeout(()=>{this.shouldReconnect&&this.connect().catch(e=>{console.error("[WebSocket] Reconnection failed:",e)})},e)}_startHeartbeat(){this.pingInterval&&(this.pingTimer=setInterval(()=>{this.isConnected&&this.socket&&(this.send("ping"),this._startPongTimeout())},this.pingInterval))}_startPongTimeout(){this.pongTimer=setTimeout(()=>{console.warn("[WebSocket] Pong timeout - connection may be stale"),this.socket?.close(1006,"Pong timeout")},this.pongTimeout)}_clearPongTimeout(){this.pongTimer&&(clearTimeout(this.pongTimer),this.pongTimer=null)}_clearTimers(){this.reconnectTimer&&(clearTimeout(this.reconnectTimer),this.reconnectTimer=null),this.pingTimer&&(clearInterval(this.pingTimer),this.pingTimer=null),this._clearPongTimeout()}static async connect(e,t={}){const n=new WebSocketClient({...t,url:e});return await n.connect(),n}}exports.WebSocketClient=WebSocketClient;
2
+ //# sourceMappingURL=WebSocketClient-D6i85jl2.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"WebSocketClient-D6i85jl2.js","sources":["../../src/core/services/WebSocketClient.js"],"sourcesContent":["/**\n * WebSocket - Real-time WebSocket client for MOJO framework\n * Provides connection management, auto-reconnect, and event integration\n */\n\nexport default class WebSocketClient {\n constructor(options = {}) {\n this.url = options.url || null;\n this.protocols = options.protocols || [];\n \n // Connection state\n this.socket = null;\n this.isConnected = false;\n this.isConnecting = false;\n this.shouldReconnect = options.autoReconnect !== false;\n \n // Reconnection settings\n this.maxReconnectAttempts = options.maxReconnectAttempts || 5;\n this.reconnectInterval = options.reconnectInterval || 3000;\n this.reconnectBackoff = options.reconnectBackoff || 1.5;\n this.reconnectAttempts = 0;\n this.reconnectTimer = null;\n \n // Heartbeat/ping settings\n this.pingInterval = options.pingInterval || 30000;\n this.pongTimeout = options.pongTimeout || 5000;\n this.pingTimer = null;\n this.pongTimer = null;\n \n // Event handling\n this.eventBus = options.eventBus || null;\n this.listeners = {};\n \n // Data transformation\n this.dataTransform = options.dataTransform || null;\n \n // Options\n this.debug = options.debug || false;\n \n // Bind methods\n this._onOpen = this._onOpen.bind(this);\n this._onMessage = this._onMessage.bind(this);\n this._onError = this._onError.bind(this);\n this._onClose = this._onClose.bind(this);\n }\n\n /**\n * Connect to WebSocket server\n * @param {string} url - WebSocket URL (optional if set in constructor)\n * @returns {Promise} Promise that resolves when connected\n */\n connect(url = null) {\n if (url) {\n this.url = url;\n }\n \n if (!this.url) {\n throw new Error('WebSocket URL is required');\n }\n \n if (this.isConnected || this.isConnecting) {\n return Promise.resolve();\n }\n \n this.isConnecting = true;\n \n return new Promise((resolve, reject) => {\n try {\n this.debug && console.log('[WebSocket] Connecting to:', this.url);\n \n this.socket = new WebSocket(this.url, this.protocols);\n \n this.socket.addEventListener('open', this._onOpen);\n this.socket.addEventListener('message', this._onMessage);\n this.socket.addEventListener('error', this._onError);\n this.socket.addEventListener('close', this._onClose);\n \n // Store promise resolvers for connection result\n this._connectResolve = resolve;\n this._connectReject = reject;\n \n } catch (error) {\n this.isConnecting = false;\n reject(error);\n }\n });\n }\n\n /**\n * Disconnect from WebSocket server\n */\n disconnect() {\n this.shouldReconnect = false;\n this._clearTimers();\n \n if (this.socket) {\n this.debug && console.log('[WebSocket] Disconnecting');\n this.socket.close(1000, 'Client disconnecting');\n }\n }\n\n /**\n * Send data to WebSocket server\n * @param {*} data - Data to send\n */\n send(data) {\n if (!this.isConnected || !this.socket) {\n throw new Error('WebSocket is not connected');\n }\n \n const message = typeof data === 'string' ? data : JSON.stringify(data);\n this.socket.send(message);\n \n this.debug && console.log('[WebSocket] Sent:', message);\n }\n\n /**\n * Add event listener\n * @param {string} event - Event name\n * @param {function} callback - Event callback\n */\n on(event, callback) {\n if (!this.listeners[event]) {\n this.listeners[event] = [];\n }\n this.listeners[event].push(callback);\n }\n\n /**\n * Remove event listener\n * @param {string} event - Event name\n * @param {function} callback - Event callback to remove\n */\n off(event, callback) {\n if (!this.listeners[event]) return;\n \n if (!callback) {\n delete this.listeners[event];\n return;\n }\n \n const index = this.listeners[event].indexOf(callback);\n if (index !== -1) {\n this.listeners[event].splice(index, 1);\n }\n }\n\n /**\n * Emit event to listeners\n * @param {string} event - Event name\n * @param {*} data - Event data\n */\n emit(event, data) {\n // Emit to local listeners\n if (this.listeners[event]) {\n this.listeners[event].forEach(callback => {\n try {\n callback(data);\n } catch (error) {\n console.error(`[WebSocket] Error in ${event} listener:`, error);\n }\n });\n }\n \n // Emit to external EventBus if available\n if (this.eventBus && typeof this.eventBus.emit === 'function') {\n this.eventBus.emit(`websocket:${event}`, {\n websocket: this,\n data\n });\n }\n }\n\n /**\n * Get current connection status\n * @returns {string} Connection status\n */\n getStatus() {\n if (this.isConnected) return 'connected';\n if (this.isConnecting) return 'connecting';\n return 'disconnected';\n }\n\n /**\n * Get connection statistics\n * @returns {object} Connection stats\n */\n getStats() {\n return {\n url: this.url,\n isConnected: this.isConnected,\n isConnecting: this.isConnecting,\n reconnectAttempts: this.reconnectAttempts,\n maxReconnectAttempts: this.maxReconnectAttempts,\n shouldReconnect: this.shouldReconnect\n };\n }\n\n // Private methods\n\n _onOpen(event) {\n this.debug && console.log('[WebSocket] Connected');\n \n this.isConnected = true;\n this.isConnecting = false;\n this.reconnectAttempts = 0;\n \n // Start heartbeat\n this._startHeartbeat();\n \n // Resolve connection promise\n if (this._connectResolve) {\n this._connectResolve();\n this._connectResolve = null;\n this._connectReject = null;\n }\n \n this.emit('connected', { url: this.url });\n }\n\n _onMessage(event) {\n this.debug && console.log('[WebSocket] Received:', event.data);\n \n let data;\n try {\n data = JSON.parse(event.data);\n } catch (error) {\n data = event.data;\n }\n \n // Handle heartbeat pong\n if (data === 'pong' || (data && data.type === 'pong')) {\n this._clearPongTimeout();\n return;\n }\n \n // Transform data if transformer provided\n if (this.dataTransform && typeof this.dataTransform === 'function') {\n try {\n data = this.dataTransform(data);\n } catch (error) {\n console.error('[WebSocket] Error transforming data:', error);\n this.emit('error', { error, originalData: data });\n return;\n }\n }\n \n this.emit('message', data);\n this.emit('data', data); // Alias for convenience\n }\n\n _onError(event) {\n console.error('[WebSocket] Error:', event);\n \n this.emit('error', { \n error: event.error || new Error('WebSocket error'),\n event \n });\n \n // Reject connection promise if still connecting\n if (this._connectReject) {\n this._connectReject(event.error || new Error('WebSocket connection failed'));\n this._connectResolve = null;\n this._connectReject = null;\n }\n }\n\n _onClose(event) {\n this.debug && console.log('[WebSocket] Closed:', event.code, event.reason);\n \n this.isConnected = false;\n this.isConnecting = false;\n \n this._clearTimers();\n \n // Clean up socket\n if (this.socket) {\n this.socket.removeEventListener('open', this._onOpen);\n this.socket.removeEventListener('message', this._onMessage);\n this.socket.removeEventListener('error', this._onError);\n this.socket.removeEventListener('close', this._onClose);\n this.socket = null;\n }\n \n this.emit('disconnected', { \n code: event.code, \n reason: event.reason,\n wasClean: event.wasClean\n });\n \n // Attempt reconnection if enabled and not a clean close\n if (this.shouldReconnect && event.code !== 1000) {\n this._attemptReconnect();\n }\n }\n\n _attemptReconnect() {\n if (this.reconnectAttempts >= this.maxReconnectAttempts) {\n this.debug && console.log('[WebSocket] Max reconnect attempts reached');\n this.emit('reconnect-failed', { \n attempts: this.reconnectAttempts,\n maxAttempts: this.maxReconnectAttempts\n });\n return;\n }\n \n this.reconnectAttempts++;\n const delay = this.reconnectInterval * Math.pow(this.reconnectBackoff, this.reconnectAttempts - 1);\n \n this.debug && console.log(`[WebSocket] Reconnecting in ${delay}ms (attempt ${this.reconnectAttempts})`);\n \n this.emit('reconnecting', { \n attempt: this.reconnectAttempts,\n delay,\n maxAttempts: this.maxReconnectAttempts\n });\n \n this.reconnectTimer = setTimeout(() => {\n if (this.shouldReconnect) {\n this.connect().catch(error => {\n console.error('[WebSocket] Reconnection failed:', error);\n });\n }\n }, delay);\n }\n\n _startHeartbeat() {\n if (!this.pingInterval) return;\n \n this.pingTimer = setInterval(() => {\n if (this.isConnected && this.socket) {\n this.send('ping');\n this._startPongTimeout();\n }\n }, this.pingInterval);\n }\n\n _startPongTimeout() {\n this.pongTimer = setTimeout(() => {\n console.warn('[WebSocket] Pong timeout - connection may be stale');\n this.socket?.close(1006, 'Pong timeout');\n }, this.pongTimeout);\n }\n\n _clearPongTimeout() {\n if (this.pongTimer) {\n clearTimeout(this.pongTimer);\n this.pongTimer = null;\n }\n }\n\n _clearTimers() {\n if (this.reconnectTimer) {\n clearTimeout(this.reconnectTimer);\n this.reconnectTimer = null;\n }\n \n if (this.pingTimer) {\n clearInterval(this.pingTimer);\n this.pingTimer = null;\n }\n \n this._clearPongTimeout();\n }\n\n /**\n * Static method to create and connect WebSocket\n * @param {string} url - WebSocket URL\n * @param {object} options - Connection options\n * @returns {Promise<WebSocketClient>} Connected WebSocket client\n */\n static async connect(url, options = {}) {\n const client = new WebSocketClient({ ...options, url });\n await client.connect();\n return client;\n }\n}"],"names":["WebSocketClient","constructor","options","this","url","protocols","socket","isConnected","isConnecting","shouldReconnect","autoReconnect","maxReconnectAttempts","reconnectInterval","reconnectBackoff","reconnectAttempts","reconnectTimer","pingInterval","pongTimeout","pingTimer","pongTimer","eventBus","listeners","dataTransform","debug","_onOpen","bind","_onMessage","_onError","_onClose","connect","Error","Promise","resolve","reject","console","log","WebSocket","addEventListener","_connectResolve","_connectReject","error","disconnect","_clearTimers","close","send","data","message","JSON","stringify","on","event","callback","push","off","index","indexOf","splice","emit","forEach","websocket","getStatus","getStats","_startHeartbeat","parse","type","_clearPongTimeout","originalData","code","reason","removeEventListener","wasClean","_attemptReconnect","attempts","maxAttempts","delay","Math","pow","attempt","setTimeout","catch","setInterval","_startPongTimeout","warn","clearTimeout","clearInterval","client"],"mappings":"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"}
@@ -0,0 +1,297 @@
1
+ class WebSocketClient {
2
+ constructor(options = {}) {
3
+ this.url = options.url || null;
4
+ this.protocols = options.protocols || [];
5
+ this.socket = null;
6
+ this.isConnected = false;
7
+ this.isConnecting = false;
8
+ this.shouldReconnect = options.autoReconnect !== false;
9
+ this.maxReconnectAttempts = options.maxReconnectAttempts || 5;
10
+ this.reconnectInterval = options.reconnectInterval || 3e3;
11
+ this.reconnectBackoff = options.reconnectBackoff || 1.5;
12
+ this.reconnectAttempts = 0;
13
+ this.reconnectTimer = null;
14
+ this.pingInterval = options.pingInterval || 3e4;
15
+ this.pongTimeout = options.pongTimeout || 5e3;
16
+ this.pingTimer = null;
17
+ this.pongTimer = null;
18
+ this.eventBus = options.eventBus || null;
19
+ this.listeners = {};
20
+ this.dataTransform = options.dataTransform || null;
21
+ this.debug = options.debug || false;
22
+ this._onOpen = this._onOpen.bind(this);
23
+ this._onMessage = this._onMessage.bind(this);
24
+ this._onError = this._onError.bind(this);
25
+ this._onClose = this._onClose.bind(this);
26
+ }
27
+ /**
28
+ * Connect to WebSocket server
29
+ * @param {string} url - WebSocket URL (optional if set in constructor)
30
+ * @returns {Promise} Promise that resolves when connected
31
+ */
32
+ connect(url = null) {
33
+ if (url) {
34
+ this.url = url;
35
+ }
36
+ if (!this.url) {
37
+ throw new Error("WebSocket URL is required");
38
+ }
39
+ if (this.isConnected || this.isConnecting) {
40
+ return Promise.resolve();
41
+ }
42
+ this.isConnecting = true;
43
+ return new Promise((resolve, reject) => {
44
+ try {
45
+ this.debug && console.log("[WebSocket] Connecting to:", this.url);
46
+ this.socket = new WebSocket(this.url, this.protocols);
47
+ this.socket.addEventListener("open", this._onOpen);
48
+ this.socket.addEventListener("message", this._onMessage);
49
+ this.socket.addEventListener("error", this._onError);
50
+ this.socket.addEventListener("close", this._onClose);
51
+ this._connectResolve = resolve;
52
+ this._connectReject = reject;
53
+ } catch (error) {
54
+ this.isConnecting = false;
55
+ reject(error);
56
+ }
57
+ });
58
+ }
59
+ /**
60
+ * Disconnect from WebSocket server
61
+ */
62
+ disconnect() {
63
+ this.shouldReconnect = false;
64
+ this._clearTimers();
65
+ if (this.socket) {
66
+ this.debug && console.log("[WebSocket] Disconnecting");
67
+ this.socket.close(1e3, "Client disconnecting");
68
+ }
69
+ }
70
+ /**
71
+ * Send data to WebSocket server
72
+ * @param {*} data - Data to send
73
+ */
74
+ send(data) {
75
+ if (!this.isConnected || !this.socket) {
76
+ throw new Error("WebSocket is not connected");
77
+ }
78
+ const message = typeof data === "string" ? data : JSON.stringify(data);
79
+ this.socket.send(message);
80
+ this.debug && console.log("[WebSocket] Sent:", message);
81
+ }
82
+ /**
83
+ * Add event listener
84
+ * @param {string} event - Event name
85
+ * @param {function} callback - Event callback
86
+ */
87
+ on(event, callback) {
88
+ if (!this.listeners[event]) {
89
+ this.listeners[event] = [];
90
+ }
91
+ this.listeners[event].push(callback);
92
+ }
93
+ /**
94
+ * Remove event listener
95
+ * @param {string} event - Event name
96
+ * @param {function} callback - Event callback to remove
97
+ */
98
+ off(event, callback) {
99
+ if (!this.listeners[event]) return;
100
+ if (!callback) {
101
+ delete this.listeners[event];
102
+ return;
103
+ }
104
+ const index = this.listeners[event].indexOf(callback);
105
+ if (index !== -1) {
106
+ this.listeners[event].splice(index, 1);
107
+ }
108
+ }
109
+ /**
110
+ * Emit event to listeners
111
+ * @param {string} event - Event name
112
+ * @param {*} data - Event data
113
+ */
114
+ emit(event, data) {
115
+ if (this.listeners[event]) {
116
+ this.listeners[event].forEach((callback) => {
117
+ try {
118
+ callback(data);
119
+ } catch (error) {
120
+ console.error(`[WebSocket] Error in ${event} listener:`, error);
121
+ }
122
+ });
123
+ }
124
+ if (this.eventBus && typeof this.eventBus.emit === "function") {
125
+ this.eventBus.emit(`websocket:${event}`, {
126
+ websocket: this,
127
+ data
128
+ });
129
+ }
130
+ }
131
+ /**
132
+ * Get current connection status
133
+ * @returns {string} Connection status
134
+ */
135
+ getStatus() {
136
+ if (this.isConnected) return "connected";
137
+ if (this.isConnecting) return "connecting";
138
+ return "disconnected";
139
+ }
140
+ /**
141
+ * Get connection statistics
142
+ * @returns {object} Connection stats
143
+ */
144
+ getStats() {
145
+ return {
146
+ url: this.url,
147
+ isConnected: this.isConnected,
148
+ isConnecting: this.isConnecting,
149
+ reconnectAttempts: this.reconnectAttempts,
150
+ maxReconnectAttempts: this.maxReconnectAttempts,
151
+ shouldReconnect: this.shouldReconnect
152
+ };
153
+ }
154
+ // Private methods
155
+ _onOpen(event) {
156
+ this.debug && console.log("[WebSocket] Connected");
157
+ this.isConnected = true;
158
+ this.isConnecting = false;
159
+ this.reconnectAttempts = 0;
160
+ this._startHeartbeat();
161
+ if (this._connectResolve) {
162
+ this._connectResolve();
163
+ this._connectResolve = null;
164
+ this._connectReject = null;
165
+ }
166
+ this.emit("connected", { url: this.url });
167
+ }
168
+ _onMessage(event) {
169
+ this.debug && console.log("[WebSocket] Received:", event.data);
170
+ let data;
171
+ try {
172
+ data = JSON.parse(event.data);
173
+ } catch (error) {
174
+ data = event.data;
175
+ }
176
+ if (data === "pong" || data && data.type === "pong") {
177
+ this._clearPongTimeout();
178
+ return;
179
+ }
180
+ if (this.dataTransform && typeof this.dataTransform === "function") {
181
+ try {
182
+ data = this.dataTransform(data);
183
+ } catch (error) {
184
+ console.error("[WebSocket] Error transforming data:", error);
185
+ this.emit("error", { error, originalData: data });
186
+ return;
187
+ }
188
+ }
189
+ this.emit("message", data);
190
+ this.emit("data", data);
191
+ }
192
+ _onError(event) {
193
+ console.error("[WebSocket] Error:", event);
194
+ this.emit("error", {
195
+ error: event.error || new Error("WebSocket error"),
196
+ event
197
+ });
198
+ if (this._connectReject) {
199
+ this._connectReject(event.error || new Error("WebSocket connection failed"));
200
+ this._connectResolve = null;
201
+ this._connectReject = null;
202
+ }
203
+ }
204
+ _onClose(event) {
205
+ this.debug && console.log("[WebSocket] Closed:", event.code, event.reason);
206
+ this.isConnected = false;
207
+ this.isConnecting = false;
208
+ this._clearTimers();
209
+ if (this.socket) {
210
+ this.socket.removeEventListener("open", this._onOpen);
211
+ this.socket.removeEventListener("message", this._onMessage);
212
+ this.socket.removeEventListener("error", this._onError);
213
+ this.socket.removeEventListener("close", this._onClose);
214
+ this.socket = null;
215
+ }
216
+ this.emit("disconnected", {
217
+ code: event.code,
218
+ reason: event.reason,
219
+ wasClean: event.wasClean
220
+ });
221
+ if (this.shouldReconnect && event.code !== 1e3) {
222
+ this._attemptReconnect();
223
+ }
224
+ }
225
+ _attemptReconnect() {
226
+ if (this.reconnectAttempts >= this.maxReconnectAttempts) {
227
+ this.debug && console.log("[WebSocket] Max reconnect attempts reached");
228
+ this.emit("reconnect-failed", {
229
+ attempts: this.reconnectAttempts,
230
+ maxAttempts: this.maxReconnectAttempts
231
+ });
232
+ return;
233
+ }
234
+ this.reconnectAttempts++;
235
+ const delay = this.reconnectInterval * Math.pow(this.reconnectBackoff, this.reconnectAttempts - 1);
236
+ this.debug && console.log(`[WebSocket] Reconnecting in ${delay}ms (attempt ${this.reconnectAttempts})`);
237
+ this.emit("reconnecting", {
238
+ attempt: this.reconnectAttempts,
239
+ delay,
240
+ maxAttempts: this.maxReconnectAttempts
241
+ });
242
+ this.reconnectTimer = setTimeout(() => {
243
+ if (this.shouldReconnect) {
244
+ this.connect().catch((error) => {
245
+ console.error("[WebSocket] Reconnection failed:", error);
246
+ });
247
+ }
248
+ }, delay);
249
+ }
250
+ _startHeartbeat() {
251
+ if (!this.pingInterval) return;
252
+ this.pingTimer = setInterval(() => {
253
+ if (this.isConnected && this.socket) {
254
+ this.send("ping");
255
+ this._startPongTimeout();
256
+ }
257
+ }, this.pingInterval);
258
+ }
259
+ _startPongTimeout() {
260
+ this.pongTimer = setTimeout(() => {
261
+ console.warn("[WebSocket] Pong timeout - connection may be stale");
262
+ this.socket?.close(1006, "Pong timeout");
263
+ }, this.pongTimeout);
264
+ }
265
+ _clearPongTimeout() {
266
+ if (this.pongTimer) {
267
+ clearTimeout(this.pongTimer);
268
+ this.pongTimer = null;
269
+ }
270
+ }
271
+ _clearTimers() {
272
+ if (this.reconnectTimer) {
273
+ clearTimeout(this.reconnectTimer);
274
+ this.reconnectTimer = null;
275
+ }
276
+ if (this.pingTimer) {
277
+ clearInterval(this.pingTimer);
278
+ this.pingTimer = null;
279
+ }
280
+ this._clearPongTimeout();
281
+ }
282
+ /**
283
+ * Static method to create and connect WebSocket
284
+ * @param {string} url - WebSocket URL
285
+ * @param {object} options - Connection options
286
+ * @returns {Promise<WebSocketClient>} Connected WebSocket client
287
+ */
288
+ static async connect(url, options = {}) {
289
+ const client = new WebSocketClient({ ...options, url });
290
+ await client.connect();
291
+ return client;
292
+ }
293
+ }
294
+ export {
295
+ WebSocketClient as W
296
+ };
297
+ //# sourceMappingURL=WebSocketClient-Dvl3AYx1.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"WebSocketClient-Dvl3AYx1.js","sources":["../../src/core/services/WebSocketClient.js"],"sourcesContent":["/**\n * WebSocket - Real-time WebSocket client for MOJO framework\n * Provides connection management, auto-reconnect, and event integration\n */\n\nexport default class WebSocketClient {\n constructor(options = {}) {\n this.url = options.url || null;\n this.protocols = options.protocols || [];\n \n // Connection state\n this.socket = null;\n this.isConnected = false;\n this.isConnecting = false;\n this.shouldReconnect = options.autoReconnect !== false;\n \n // Reconnection settings\n this.maxReconnectAttempts = options.maxReconnectAttempts || 5;\n this.reconnectInterval = options.reconnectInterval || 3000;\n this.reconnectBackoff = options.reconnectBackoff || 1.5;\n this.reconnectAttempts = 0;\n this.reconnectTimer = null;\n \n // Heartbeat/ping settings\n this.pingInterval = options.pingInterval || 30000;\n this.pongTimeout = options.pongTimeout || 5000;\n this.pingTimer = null;\n this.pongTimer = null;\n \n // Event handling\n this.eventBus = options.eventBus || null;\n this.listeners = {};\n \n // Data transformation\n this.dataTransform = options.dataTransform || null;\n \n // Options\n this.debug = options.debug || false;\n \n // Bind methods\n this._onOpen = this._onOpen.bind(this);\n this._onMessage = this._onMessage.bind(this);\n this._onError = this._onError.bind(this);\n this._onClose = this._onClose.bind(this);\n }\n\n /**\n * Connect to WebSocket server\n * @param {string} url - WebSocket URL (optional if set in constructor)\n * @returns {Promise} Promise that resolves when connected\n */\n connect(url = null) {\n if (url) {\n this.url = url;\n }\n \n if (!this.url) {\n throw new Error('WebSocket URL is required');\n }\n \n if (this.isConnected || this.isConnecting) {\n return Promise.resolve();\n }\n \n this.isConnecting = true;\n \n return new Promise((resolve, reject) => {\n try {\n this.debug && console.log('[WebSocket] Connecting to:', this.url);\n \n this.socket = new WebSocket(this.url, this.protocols);\n \n this.socket.addEventListener('open', this._onOpen);\n this.socket.addEventListener('message', this._onMessage);\n this.socket.addEventListener('error', this._onError);\n this.socket.addEventListener('close', this._onClose);\n \n // Store promise resolvers for connection result\n this._connectResolve = resolve;\n this._connectReject = reject;\n \n } catch (error) {\n this.isConnecting = false;\n reject(error);\n }\n });\n }\n\n /**\n * Disconnect from WebSocket server\n */\n disconnect() {\n this.shouldReconnect = false;\n this._clearTimers();\n \n if (this.socket) {\n this.debug && console.log('[WebSocket] Disconnecting');\n this.socket.close(1000, 'Client disconnecting');\n }\n }\n\n /**\n * Send data to WebSocket server\n * @param {*} data - Data to send\n */\n send(data) {\n if (!this.isConnected || !this.socket) {\n throw new Error('WebSocket is not connected');\n }\n \n const message = typeof data === 'string' ? data : JSON.stringify(data);\n this.socket.send(message);\n \n this.debug && console.log('[WebSocket] Sent:', message);\n }\n\n /**\n * Add event listener\n * @param {string} event - Event name\n * @param {function} callback - Event callback\n */\n on(event, callback) {\n if (!this.listeners[event]) {\n this.listeners[event] = [];\n }\n this.listeners[event].push(callback);\n }\n\n /**\n * Remove event listener\n * @param {string} event - Event name\n * @param {function} callback - Event callback to remove\n */\n off(event, callback) {\n if (!this.listeners[event]) return;\n \n if (!callback) {\n delete this.listeners[event];\n return;\n }\n \n const index = this.listeners[event].indexOf(callback);\n if (index !== -1) {\n this.listeners[event].splice(index, 1);\n }\n }\n\n /**\n * Emit event to listeners\n * @param {string} event - Event name\n * @param {*} data - Event data\n */\n emit(event, data) {\n // Emit to local listeners\n if (this.listeners[event]) {\n this.listeners[event].forEach(callback => {\n try {\n callback(data);\n } catch (error) {\n console.error(`[WebSocket] Error in ${event} listener:`, error);\n }\n });\n }\n \n // Emit to external EventBus if available\n if (this.eventBus && typeof this.eventBus.emit === 'function') {\n this.eventBus.emit(`websocket:${event}`, {\n websocket: this,\n data\n });\n }\n }\n\n /**\n * Get current connection status\n * @returns {string} Connection status\n */\n getStatus() {\n if (this.isConnected) return 'connected';\n if (this.isConnecting) return 'connecting';\n return 'disconnected';\n }\n\n /**\n * Get connection statistics\n * @returns {object} Connection stats\n */\n getStats() {\n return {\n url: this.url,\n isConnected: this.isConnected,\n isConnecting: this.isConnecting,\n reconnectAttempts: this.reconnectAttempts,\n maxReconnectAttempts: this.maxReconnectAttempts,\n shouldReconnect: this.shouldReconnect\n };\n }\n\n // Private methods\n\n _onOpen(event) {\n this.debug && console.log('[WebSocket] Connected');\n \n this.isConnected = true;\n this.isConnecting = false;\n this.reconnectAttempts = 0;\n \n // Start heartbeat\n this._startHeartbeat();\n \n // Resolve connection promise\n if (this._connectResolve) {\n this._connectResolve();\n this._connectResolve = null;\n this._connectReject = null;\n }\n \n this.emit('connected', { url: this.url });\n }\n\n _onMessage(event) {\n this.debug && console.log('[WebSocket] Received:', event.data);\n \n let data;\n try {\n data = JSON.parse(event.data);\n } catch (error) {\n data = event.data;\n }\n \n // Handle heartbeat pong\n if (data === 'pong' || (data && data.type === 'pong')) {\n this._clearPongTimeout();\n return;\n }\n \n // Transform data if transformer provided\n if (this.dataTransform && typeof this.dataTransform === 'function') {\n try {\n data = this.dataTransform(data);\n } catch (error) {\n console.error('[WebSocket] Error transforming data:', error);\n this.emit('error', { error, originalData: data });\n return;\n }\n }\n \n this.emit('message', data);\n this.emit('data', data); // Alias for convenience\n }\n\n _onError(event) {\n console.error('[WebSocket] Error:', event);\n \n this.emit('error', { \n error: event.error || new Error('WebSocket error'),\n event \n });\n \n // Reject connection promise if still connecting\n if (this._connectReject) {\n this._connectReject(event.error || new Error('WebSocket connection failed'));\n this._connectResolve = null;\n this._connectReject = null;\n }\n }\n\n _onClose(event) {\n this.debug && console.log('[WebSocket] Closed:', event.code, event.reason);\n \n this.isConnected = false;\n this.isConnecting = false;\n \n this._clearTimers();\n \n // Clean up socket\n if (this.socket) {\n this.socket.removeEventListener('open', this._onOpen);\n this.socket.removeEventListener('message', this._onMessage);\n this.socket.removeEventListener('error', this._onError);\n this.socket.removeEventListener('close', this._onClose);\n this.socket = null;\n }\n \n this.emit('disconnected', { \n code: event.code, \n reason: event.reason,\n wasClean: event.wasClean\n });\n \n // Attempt reconnection if enabled and not a clean close\n if (this.shouldReconnect && event.code !== 1000) {\n this._attemptReconnect();\n }\n }\n\n _attemptReconnect() {\n if (this.reconnectAttempts >= this.maxReconnectAttempts) {\n this.debug && console.log('[WebSocket] Max reconnect attempts reached');\n this.emit('reconnect-failed', { \n attempts: this.reconnectAttempts,\n maxAttempts: this.maxReconnectAttempts\n });\n return;\n }\n \n this.reconnectAttempts++;\n const delay = this.reconnectInterval * Math.pow(this.reconnectBackoff, this.reconnectAttempts - 1);\n \n this.debug && console.log(`[WebSocket] Reconnecting in ${delay}ms (attempt ${this.reconnectAttempts})`);\n \n this.emit('reconnecting', { \n attempt: this.reconnectAttempts,\n delay,\n maxAttempts: this.maxReconnectAttempts\n });\n \n this.reconnectTimer = setTimeout(() => {\n if (this.shouldReconnect) {\n this.connect().catch(error => {\n console.error('[WebSocket] Reconnection failed:', error);\n });\n }\n }, delay);\n }\n\n _startHeartbeat() {\n if (!this.pingInterval) return;\n \n this.pingTimer = setInterval(() => {\n if (this.isConnected && this.socket) {\n this.send('ping');\n this._startPongTimeout();\n }\n }, this.pingInterval);\n }\n\n _startPongTimeout() {\n this.pongTimer = setTimeout(() => {\n console.warn('[WebSocket] Pong timeout - connection may be stale');\n this.socket?.close(1006, 'Pong timeout');\n }, this.pongTimeout);\n }\n\n _clearPongTimeout() {\n if (this.pongTimer) {\n clearTimeout(this.pongTimer);\n this.pongTimer = null;\n }\n }\n\n _clearTimers() {\n if (this.reconnectTimer) {\n clearTimeout(this.reconnectTimer);\n this.reconnectTimer = null;\n }\n \n if (this.pingTimer) {\n clearInterval(this.pingTimer);\n this.pingTimer = null;\n }\n \n this._clearPongTimeout();\n }\n\n /**\n * Static method to create and connect WebSocket\n * @param {string} url - WebSocket URL\n * @param {object} options - Connection options\n * @returns {Promise<WebSocketClient>} Connected WebSocket client\n */\n static async connect(url, options = {}) {\n const client = new WebSocketClient({ ...options, url });\n await client.connect();\n return client;\n }\n}"],"names":[],"mappings":"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"}