web-mojo 2.1.1108 → 2.1.1110
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/admin.cjs.js +1 -1
- package/dist/admin.cjs.js.map +1 -1
- package/dist/admin.es.js +18 -16
- package/dist/admin.es.js.map +1 -1
- package/dist/auth.cjs.js +1 -1
- package/dist/auth.es.js +1 -1
- package/dist/charts.cjs.js +1 -1
- package/dist/charts.css +118 -0
- package/dist/charts.es.js +4 -4
- package/dist/chat.css +3 -18
- package/dist/chunks/{ChatView-CTe1wlQP.js → ChatView-BsANcDiL.js} +31 -8
- package/dist/chunks/ChatView-BsANcDiL.js.map +1 -0
- package/dist/chunks/{ChatView-BL4kPmQd.js → ChatView-DSEEMnNt.js} +2 -2
- package/dist/chunks/ChatView-DSEEMnNt.js.map +1 -0
- package/dist/chunks/{Collection-Ds4EOzap.js → Collection-CqLcHgQG.js} +2 -2
- package/dist/chunks/{Collection-Ds4EOzap.js.map → Collection-CqLcHgQG.js.map} +1 -1
- package/dist/chunks/{Collection-bgdNt0wV.js → Collection-vtImpCcS.js} +2 -2
- package/dist/chunks/{Collection-bgdNt0wV.js.map → Collection-vtImpCcS.js.map} +1 -1
- package/dist/chunks/{ContextMenu-DwvxeWLt.js → ContextMenu-BY3BgxM5.js} +2 -2
- package/dist/chunks/{ContextMenu-DwvxeWLt.js.map → ContextMenu-BY3BgxM5.js.map} +1 -1
- package/dist/chunks/{ContextMenu-KHTc-Ubo.js → ContextMenu-DfrWFc5y.js} +3 -3
- package/dist/chunks/{ContextMenu-KHTc-Ubo.js.map → ContextMenu-DfrWFc5y.js.map} +1 -1
- package/dist/chunks/{DataView-DbexZltc.js → DataView-CHvoEI4M.js} +2 -2
- package/dist/chunks/{DataView-DbexZltc.js.map → DataView-CHvoEI4M.js.map} +1 -1
- package/dist/chunks/{DataView-DAGqpR7b.js → DataView-CsYXM9vF.js} +2 -2
- package/dist/chunks/{DataView-DAGqpR7b.js.map → DataView-CsYXM9vF.js.map} +1 -1
- package/dist/chunks/{Dialog-DE-21f_8.js → Dialog-BKPwBCDC.js} +2 -2
- package/dist/chunks/Dialog-BKPwBCDC.js.map +1 -0
- package/dist/chunks/{Dialog-CXOsYNLf.js → Dialog-D4DsB-N1.js} +6 -6
- package/dist/chunks/Dialog-D4DsB-N1.js.map +1 -0
- package/dist/chunks/{FormView-Dya3nBrn.js → FormView-B9nIO_AX.js} +2 -2
- package/dist/chunks/{FormView-Dya3nBrn.js.map → FormView-B9nIO_AX.js.map} +1 -1
- package/dist/chunks/{FormView-DbPZwhZ6.js → FormView-DYX_yeho.js} +2 -2
- package/dist/chunks/{FormView-DbPZwhZ6.js.map → FormView-DYX_yeho.js.map} +1 -1
- package/dist/chunks/{ListView-DFP4ie99.js → ListView-BtZ7fylv.js} +3 -3
- package/dist/chunks/{ListView-DFP4ie99.js.map → ListView-BtZ7fylv.js.map} +1 -1
- package/dist/chunks/{ListView-BQgv3OvQ.js → ListView-D2vt0koT.js} +2 -2
- package/dist/chunks/{ListView-BQgv3OvQ.js.map → ListView-D2vt0koT.js.map} +1 -1
- package/dist/chunks/{MetricsMiniChartWidget-DOcsPk5u.js → MetricsMiniChartWidget-BJJY9R-s.js} +2 -2
- package/dist/chunks/MetricsMiniChartWidget-BJJY9R-s.js.map +1 -0
- package/dist/chunks/{MetricsMiniChartWidget-Dan8l57G.js → MetricsMiniChartWidget-bmnV82d1.js} +340 -9
- package/dist/chunks/{MetricsMiniChartWidget-Dan8l57G.js.map → MetricsMiniChartWidget-bmnV82d1.js.map} +1 -1
- package/dist/chunks/{PDFViewer-B1g6Q6ae.js → PDFViewer-Bzifr-dn.js} +3 -3
- package/dist/chunks/{PDFViewer-B1g6Q6ae.js.map → PDFViewer-Bzifr-dn.js.map} +1 -1
- package/dist/chunks/{PDFViewer-DDb7xLGo.js → PDFViewer-Cgr3T15i.js} +2 -2
- package/dist/chunks/{PDFViewer-DDb7xLGo.js.map → PDFViewer-Cgr3T15i.js.map} +1 -1
- package/dist/chunks/{Rest-C3KvOEeY.js → Rest-C3fPzCIA.js} +2 -2
- package/dist/chunks/Rest-C3fPzCIA.js.map +1 -0
- package/dist/chunks/{Rest-BIyXKaFn.js → Rest-DYPLEzNy.js} +2 -2
- package/dist/chunks/Rest-DYPLEzNy.js.map +1 -0
- package/dist/chunks/{TokenManager-DUmZuAKG.js → TokenManager-CKkIWgzy.js} +6 -6
- package/dist/chunks/TokenManager-CKkIWgzy.js.map +1 -0
- package/dist/chunks/TokenManager-DSyRWlvc.js +2 -0
- package/dist/chunks/TokenManager-DSyRWlvc.js.map +1 -0
- package/dist/chunks/{WebSocketClient-CGQLSIgP.js → WebSocketClient-CkAL55qy.js} +2 -2
- package/dist/chunks/{WebSocketClient-CGQLSIgP.js.map → WebSocketClient-CkAL55qy.js.map} +1 -1
- package/dist/chunks/{WebSocketClient-sEN2DmCF.js → WebSocketClient-Dzwprd15.js} +2 -2
- package/dist/chunks/{WebSocketClient-sEN2DmCF.js.map → WebSocketClient-Dzwprd15.js.map} +1 -1
- package/dist/chunks/{version-DIk6UpNb.js → version-C5lFa1F0.js} +2 -2
- package/dist/chunks/{version-DIk6UpNb.js.map → version-C5lFa1F0.js.map} +1 -1
- package/dist/chunks/{version-CrckCqr_.js → version-FRgkiWti.js} +4 -4
- package/dist/chunks/{version-CrckCqr_.js.map → version-FRgkiWti.js.map} +1 -1
- package/dist/core.css +58 -52
- package/dist/css/web-mojo.css +1 -1
- package/dist/docit.cjs.js +1 -1
- package/dist/docit.es.js +6 -6
- package/dist/index.cjs.js +1 -1
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.es.js +71 -132
- package/dist/index.es.js.map +1 -1
- package/dist/lightbox.cjs.js +1 -1
- package/dist/lightbox.es.js +5 -5
- package/dist/map.cjs.js +1 -1
- package/dist/map.es.js +2 -2
- package/dist/timeline.cjs.js +1 -1
- package/dist/timeline.es.js +4 -4
- package/package.json +1 -1
- package/dist/chunks/ChatView-BL4kPmQd.js.map +0 -1
- package/dist/chunks/ChatView-CTe1wlQP.js.map +0 -1
- package/dist/chunks/Dialog-CXOsYNLf.js.map +0 -1
- package/dist/chunks/Dialog-DE-21f_8.js.map +0 -1
- package/dist/chunks/MetricsMiniChartWidget-DOcsPk5u.js.map +0 -1
- package/dist/chunks/Rest-BIyXKaFn.js.map +0 -1
- package/dist/chunks/Rest-C3KvOEeY.js.map +0 -1
- package/dist/chunks/TokenManager-B0Z_dd7k.js +0 -2
- package/dist/chunks/TokenManager-B0Z_dd7k.js.map +0 -1
- package/dist/chunks/TokenManager-DUmZuAKG.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"WebSocketClient-CGQLSIgP.js","sources":["../../src/core/services/WebSocketClient.js"],"sourcesContent":["/**\n * WebSocketClient - Simple, robust WebSocket client with auto-reconnect\n *\n * Features:\n * - Auto-reconnect with exponential backoff\n * - Heartbeat ping/pong with timeout disconnect\n * - Event-driven architecture using EventEmitter\n * - Token-based authentication\n *\n * Usage:\n * const ws = new WebSocketClient({\n * url: \"wss://api.example.com/ws/realtime\",\n * tokenPrefix: \"bearer\",\n * getToken: () => app.tokenManager.getToken()\n * });\n *\n * ws.on('connected', () => console.log('Connected!'));\n * ws.on('message', (data) => console.log('Received:', data));\n * ws.connect();\n */\n\nimport EventEmitter from '@core/mixins/EventEmitter.js';\n\nclass WebSocketClient {\n constructor(options = {}) {\n // Connection\n this.url = options.url;\n this.socket = null;\n this.isConnected = false;\n this.isConnecting = false;\n\n // Auth\n this.getToken = options.getToken || null;\n this.tokenPrefix = options.tokenPrefix || 'bearer';\n\n // Reconnection\n this.shouldReconnect = options.autoReconnect !== false;\n this.maxReconnectAttempts = options.maxReconnectAttempts || Infinity;\n this.reconnectInterval = options.reconnectInterval || 3000;\n this.reconnectBackoff = options.reconnectBackoff || 1.5;\n this.reconnectAttempts = 0;\n this.reconnectTimer = null;\n\n // Heartbeat\n this.pingInterval = options.pingInterval || 30000;\n this.pongTimeout = options.pongTimeout || 5000;\n this.pingTimer = null;\n this.pongTimer = null;\n\n // Debug\n this.debug = options.debug || false;\n }\n\n /**\n * Connect to WebSocket server\n */\n async connect(url = null) {\n if (url) this.url = url;\n if (!this.url) throw new Error('WebSocket URL is required');\n if (this.isConnected || this.isConnecting) return;\n\n this.isConnecting = true;\n this._log('Connecting to:', this.url);\n\n return new Promise((resolve, reject) => {\n try {\n this.socket = new WebSocket(this.url);\n\n this.socket.onopen = () => {\n this._log('Connected');\n this.isConnected = true;\n this.isConnecting = false;\n this.reconnectAttempts = 0;\n\n this._authenticate();\n this._startHeartbeat();\n\n this.emit('connected');\n resolve();\n };\n\n this.socket.onmessage = (event) => this._handleMessage(event);\n this.socket.onerror = (event) => this._handleError(event, reject);\n this.socket.onclose = (event) => this._handleClose(event);\n\n } catch (error) {\n this.isConnecting = false;\n reject(error);\n }\n });\n }\n\n /**\n * Disconnect from server\n */\n disconnect() {\n this.shouldReconnect = false;\n this._clearTimers();\n\n if (this.socket) {\n this._log('Disconnecting');\n this.socket.close(1000, 'Client disconnect');\n }\n }\n\n /**\n * Send data (auto-stringifies objects)\n */\n send(data) {\n if (!this.isConnected) {\n throw new Error('WebSocket not connected');\n }\n\n const message = typeof data === 'string' ? data : JSON.stringify(data);\n this.socket.send(message);\n this._log('Sent:', message);\n }\n\n // Private methods\n\n _authenticate() {\n const token = this.getToken ? this.getToken() : null;\n if (!token) {\n console.warn('[WebSocket] No token available');\n return;\n }\n\n this.send({\n type: 'authenticate',\n token,\n prefix: this.tokenPrefix\n });\n }\n\n _handleMessage(event) {\n this._log('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 pong response\n if (data?.type === 'pong') {\n this._clearPongTimeout();\n return;\n }\n\n // Emit specific event types\n if (data?.type) {\n this.emit(`message:${data.type}`, data);\n }\n\n // Always emit generic message event\n this.emit('message', data);\n }\n\n _handleError(event, rejectFn) {\n console.error('[WebSocket] Error:', event);\n this.emit('error', event);\n\n if (rejectFn) {\n rejectFn(new Error('WebSocket connection failed'));\n }\n }\n\n _handleClose(event) {\n this._log('Closed:', event.code, event.reason);\n\n this.isConnected = false;\n this.isConnecting = false;\n this._clearTimers();\n this.socket = null;\n\n this.emit('disconnected', {\n code: event.code,\n reason: event.reason,\n wasClean: event.wasClean\n });\n\n // Auto-reconnect (except for clean closes)\n if (this.shouldReconnect && event.code !== 1000) {\n this._reconnect();\n }\n }\n\n _reconnect() {\n if (this.reconnectAttempts >= this.maxReconnectAttempts) {\n this._log('Max reconnect attempts reached');\n this.emit('reconnect-failed', { attempts: this.reconnectAttempts });\n return;\n }\n\n this.reconnectAttempts++;\n const delay = this.reconnectInterval * Math.pow(this.reconnectBackoff, this.reconnectAttempts - 1);\n\n this._log(`Reconnecting in ${delay}ms (attempt ${this.reconnectAttempts})`);\n this.emit('reconnecting', { attempt: this.reconnectAttempts, delay });\n\n this.reconnectTimer = setTimeout(() => {\n if (this.shouldReconnect) {\n this.connect().catch(err => console.error('[WebSocket] Reconnect failed:', err));\n }\n }, delay);\n }\n\n _startHeartbeat() {\n if (!this.pingInterval) return;\n\n this.pingTimer = setInterval(() => {\n if (this.isConnected) {\n this.send({ action: 'ping' });\n this._startPongTimeout();\n }\n }, this.pingInterval);\n }\n\n _startPongTimeout() {\n this._clearPongTimeout();\n\n this.pongTimer = setTimeout(() => {\n console.warn('[WebSocket] Pong timeout - closing connection');\n if (this.socket) {\n this.socket.close(1006, 'Pong timeout');\n }\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 if (this.pingTimer) {\n clearInterval(this.pingTimer);\n this.pingTimer = null;\n }\n this._clearPongTimeout();\n }\n\n _log(...args) {\n if (this.debug) {\n console.log('[WebSocket]', ...args);\n }\n }\n\n // Static methods\n\n /**\n * Convert REST API base URL to WebSocket URL\n * @param {string} baseURL - REST API base URL (http/https)\n * @param {string} path - WebSocket path (default: '/ws')\n * @returns {string} WebSocket URL (ws/wss)\n *\n * @example\n * WebSocketClient.deriveURL('https://api.example.com', '/ws/realtime')\n * // Returns: 'wss://api.example.com/ws/realtime'\n *\n * WebSocketClient.deriveURL('http://localhost:3000')\n * // Returns: 'ws://localhost:3000/ws'\n */\n static deriveURL(baseURL, path = '/ws/realtime/') {\n if (!baseURL) throw new Error('baseURL is required');\n\n // Parse the base URL\n const url = new URL(baseURL);\n\n // Convert http(s) to ws(s)\n url.protocol = url.protocol === 'https:' ? 'wss:' : 'ws:';\n\n // Set the path (ensure it starts with /)\n url.pathname = path.startsWith('/') ? path : `/${path}`;\n\n return url.toString();\n }\n}\n\n// Add EventEmitter mixin\nObject.assign(WebSocketClient.prototype, EventEmitter);\n\nexport default WebSocketClient;\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"WebSocketClient-CkAL55qy.js","sources":["../../src/core/services/WebSocketClient.js"],"sourcesContent":["/**\n * WebSocketClient - Simple, robust WebSocket client with auto-reconnect\n *\n * Features:\n * - Auto-reconnect with exponential backoff\n * - Heartbeat ping/pong with timeout disconnect\n * - Event-driven architecture using EventEmitter\n * - Token-based authentication\n *\n * Usage:\n * const ws = new WebSocketClient({\n * url: \"wss://api.example.com/ws/realtime\",\n * tokenPrefix: \"bearer\",\n * getToken: () => app.tokenManager.getToken()\n * });\n *\n * ws.on('connected', () => console.log('Connected!'));\n * ws.on('message', (data) => console.log('Received:', data));\n * ws.connect();\n */\n\nimport EventEmitter from '@core/mixins/EventEmitter.js';\n\nclass WebSocketClient {\n constructor(options = {}) {\n // Connection\n this.url = options.url;\n this.socket = null;\n this.isConnected = false;\n this.isConnecting = false;\n\n // Auth\n this.getToken = options.getToken || null;\n this.tokenPrefix = options.tokenPrefix || 'bearer';\n\n // Reconnection\n this.shouldReconnect = options.autoReconnect !== false;\n this.maxReconnectAttempts = options.maxReconnectAttempts || Infinity;\n this.reconnectInterval = options.reconnectInterval || 3000;\n this.reconnectBackoff = options.reconnectBackoff || 1.5;\n this.reconnectAttempts = 0;\n this.reconnectTimer = null;\n\n // Heartbeat\n this.pingInterval = options.pingInterval || 30000;\n this.pongTimeout = options.pongTimeout || 5000;\n this.pingTimer = null;\n this.pongTimer = null;\n\n // Debug\n this.debug = options.debug || false;\n }\n\n /**\n * Connect to WebSocket server\n */\n async connect(url = null) {\n if (url) this.url = url;\n if (!this.url) throw new Error('WebSocket URL is required');\n if (this.isConnected || this.isConnecting) return;\n\n this.isConnecting = true;\n this._log('Connecting to:', this.url);\n\n return new Promise((resolve, reject) => {\n try {\n this.socket = new WebSocket(this.url);\n\n this.socket.onopen = () => {\n this._log('Connected');\n this.isConnected = true;\n this.isConnecting = false;\n this.reconnectAttempts = 0;\n\n this._authenticate();\n this._startHeartbeat();\n\n this.emit('connected');\n resolve();\n };\n\n this.socket.onmessage = (event) => this._handleMessage(event);\n this.socket.onerror = (event) => this._handleError(event, reject);\n this.socket.onclose = (event) => this._handleClose(event);\n\n } catch (error) {\n this.isConnecting = false;\n reject(error);\n }\n });\n }\n\n /**\n * Disconnect from server\n */\n disconnect() {\n this.shouldReconnect = false;\n this._clearTimers();\n\n if (this.socket) {\n this._log('Disconnecting');\n this.socket.close(1000, 'Client disconnect');\n }\n }\n\n /**\n * Send data (auto-stringifies objects)\n */\n send(data) {\n if (!this.isConnected) {\n throw new Error('WebSocket not connected');\n }\n\n const message = typeof data === 'string' ? data : JSON.stringify(data);\n this.socket.send(message);\n this._log('Sent:', message);\n }\n\n // Private methods\n\n _authenticate() {\n const token = this.getToken ? this.getToken() : null;\n if (!token) {\n console.warn('[WebSocket] No token available');\n return;\n }\n\n this.send({\n type: 'authenticate',\n token,\n prefix: this.tokenPrefix\n });\n }\n\n _handleMessage(event) {\n this._log('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 pong response\n if (data?.type === 'pong') {\n this._clearPongTimeout();\n return;\n }\n\n // Emit specific event types\n if (data?.type) {\n this.emit(`message:${data.type}`, data);\n }\n\n // Always emit generic message event\n this.emit('message', data);\n }\n\n _handleError(event, rejectFn) {\n console.error('[WebSocket] Error:', event);\n this.emit('error', event);\n\n if (rejectFn) {\n rejectFn(new Error('WebSocket connection failed'));\n }\n }\n\n _handleClose(event) {\n this._log('Closed:', event.code, event.reason);\n\n this.isConnected = false;\n this.isConnecting = false;\n this._clearTimers();\n this.socket = null;\n\n this.emit('disconnected', {\n code: event.code,\n reason: event.reason,\n wasClean: event.wasClean\n });\n\n // Auto-reconnect (except for clean closes)\n if (this.shouldReconnect && event.code !== 1000) {\n this._reconnect();\n }\n }\n\n _reconnect() {\n if (this.reconnectAttempts >= this.maxReconnectAttempts) {\n this._log('Max reconnect attempts reached');\n this.emit('reconnect-failed', { attempts: this.reconnectAttempts });\n return;\n }\n\n this.reconnectAttempts++;\n const delay = this.reconnectInterval * Math.pow(this.reconnectBackoff, this.reconnectAttempts - 1);\n\n this._log(`Reconnecting in ${delay}ms (attempt ${this.reconnectAttempts})`);\n this.emit('reconnecting', { attempt: this.reconnectAttempts, delay });\n\n this.reconnectTimer = setTimeout(() => {\n if (this.shouldReconnect) {\n this.connect().catch(err => console.error('[WebSocket] Reconnect failed:', err));\n }\n }, delay);\n }\n\n _startHeartbeat() {\n if (!this.pingInterval) return;\n\n this.pingTimer = setInterval(() => {\n if (this.isConnected) {\n this.send({ action: 'ping' });\n this._startPongTimeout();\n }\n }, this.pingInterval);\n }\n\n _startPongTimeout() {\n this._clearPongTimeout();\n\n this.pongTimer = setTimeout(() => {\n console.warn('[WebSocket] Pong timeout - closing connection');\n if (this.socket) {\n this.socket.close(1006, 'Pong timeout');\n }\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 if (this.pingTimer) {\n clearInterval(this.pingTimer);\n this.pingTimer = null;\n }\n this._clearPongTimeout();\n }\n\n _log(...args) {\n if (this.debug) {\n console.log('[WebSocket]', ...args);\n }\n }\n\n // Static methods\n\n /**\n * Convert REST API base URL to WebSocket URL\n * @param {string} baseURL - REST API base URL (http/https)\n * @param {string} path - WebSocket path (default: '/ws')\n * @returns {string} WebSocket URL (ws/wss)\n *\n * @example\n * WebSocketClient.deriveURL('https://api.example.com', '/ws/realtime')\n * // Returns: 'wss://api.example.com/ws/realtime'\n *\n * WebSocketClient.deriveURL('http://localhost:3000')\n * // Returns: 'ws://localhost:3000/ws'\n */\n static deriveURL(baseURL, path = '/ws/realtime/') {\n if (!baseURL) throw new Error('baseURL is required');\n\n // Parse the base URL\n const url = new URL(baseURL);\n\n // Convert http(s) to ws(s)\n url.protocol = url.protocol === 'https:' ? 'wss:' : 'ws:';\n\n // Set the path (ensure it starts with /)\n url.pathname = path.startsWith('/') ? path : `/${path}`;\n\n return url.toString();\n }\n}\n\n// Add EventEmitter mixin\nObject.assign(WebSocketClient.prototype, EventEmitter);\n\nexport default WebSocketClient;\n"],"names":[],"mappings":";AAuBA,MAAM,gBAAgB;AAAA,EACpB,YAAY,UAAU,IAAI;AAExB,SAAK,MAAM,QAAQ;AACnB,SAAK,SAAS;AACd,SAAK,cAAc;AACnB,SAAK,eAAe;AAGpB,SAAK,WAAW,QAAQ,YAAY;AACpC,SAAK,cAAc,QAAQ,eAAe;AAG1C,SAAK,kBAAkB,QAAQ,kBAAkB;AACjD,SAAK,uBAAuB,QAAQ,wBAAwB;AAC5D,SAAK,oBAAoB,QAAQ,qBAAqB;AACtD,SAAK,mBAAmB,QAAQ,oBAAoB;AACpD,SAAK,oBAAoB;AACzB,SAAK,iBAAiB;AAGtB,SAAK,eAAe,QAAQ,gBAAgB;AAC5C,SAAK,cAAc,QAAQ,eAAe;AAC1C,SAAK,YAAY;AACjB,SAAK,YAAY;AAGjB,SAAK,QAAQ,QAAQ,SAAS;AAAA,EAChC;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,QAAQ,MAAM,MAAM;AACxB,QAAI,IAAK,MAAK,MAAM;AACpB,QAAI,CAAC,KAAK,IAAK,OAAM,IAAI,MAAM,2BAA2B;AAC1D,QAAI,KAAK,eAAe,KAAK,aAAc;AAE3C,SAAK,eAAe;AACpB,SAAK,KAAK,kBAAkB,KAAK,GAAG;AAEpC,WAAO,IAAI,QAAQ,CAAC,SAAS,WAAW;AACtC,UAAI;AACF,aAAK,SAAS,IAAI,UAAU,KAAK,GAAG;AAEpC,aAAK,OAAO,SAAS,MAAM;AACzB,eAAK,KAAK,WAAW;AACrB,eAAK,cAAc;AACnB,eAAK,eAAe;AACpB,eAAK,oBAAoB;AAEzB,eAAK,cAAa;AAClB,eAAK,gBAAe;AAEpB,eAAK,KAAK,WAAW;AACrB,kBAAO;AAAA,QACT;AAEA,aAAK,OAAO,YAAY,CAAC,UAAU,KAAK,eAAe,KAAK;AAC5D,aAAK,OAAO,UAAU,CAAC,UAAU,KAAK,aAAa,OAAO,MAAM;AAChE,aAAK,OAAO,UAAU,CAAC,UAAU,KAAK,aAAa,KAAK;AAAA,MAE1D,SAAS,OAAO;AACd,aAAK,eAAe;AACpB,eAAO,KAAK;AAAA,MACd;AAAA,IACF,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA,EAKA,aAAa;AACX,SAAK,kBAAkB;AACvB,SAAK,aAAY;AAEjB,QAAI,KAAK,QAAQ;AACf,WAAK,KAAK,eAAe;AACzB,WAAK,OAAO,MAAM,KAAM,mBAAmB;AAAA,IAC7C;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,KAAK,MAAM;AACT,QAAI,CAAC,KAAK,aAAa;AACrB,YAAM,IAAI,MAAM,yBAAyB;AAAA,IAC3C;AAEA,UAAM,UAAU,OAAO,SAAS,WAAW,OAAO,KAAK,UAAU,IAAI;AACrE,SAAK,OAAO,KAAK,OAAO;AACxB,SAAK,KAAK,SAAS,OAAO;AAAA,EAC5B;AAAA;AAAA,EAIA,gBAAgB;AACd,UAAM,QAAQ,KAAK,WAAW,KAAK,SAAQ,IAAK;AAChD,QAAI,CAAC,OAAO;AACV,cAAQ,KAAK,gCAAgC;AAC7C;AAAA,IACF;AAEA,SAAK,KAAK;AAAA,MACR,MAAM;AAAA,MACN;AAAA,MACA,QAAQ,KAAK;AAAA,IACnB,CAAK;AAAA,EACH;AAAA,EAEA,eAAe,OAAO;AACpB,SAAK,KAAK,aAAa,MAAM,IAAI;AAEjC,QAAI;AACJ,QAAI;AACF,aAAO,KAAK,MAAM,MAAM,IAAI;AAAA,IAC9B,SAAS,OAAO;AACd,aAAO,MAAM;AAAA,IACf;AAGA,QAAI,MAAM,SAAS,QAAQ;AACzB,WAAK,kBAAiB;AACtB;AAAA,IACF;AAGA,QAAI,MAAM,MAAM;AACd,WAAK,KAAK,WAAW,KAAK,IAAI,IAAI,IAAI;AAAA,IACxC;AAGA,SAAK,KAAK,WAAW,IAAI;AAAA,EAC3B;AAAA,EAEA,aAAa,OAAO,UAAU;AAC5B,YAAQ,MAAM,sBAAsB,KAAK;AACzC,SAAK,KAAK,SAAS,KAAK;AAExB,QAAI,UAAU;AACZ,eAAS,IAAI,MAAM,6BAA6B,CAAC;AAAA,IACnD;AAAA,EACF;AAAA,EAEA,aAAa,OAAO;AAClB,SAAK,KAAK,WAAW,MAAM,MAAM,MAAM,MAAM;AAE7C,SAAK,cAAc;AACnB,SAAK,eAAe;AACpB,SAAK,aAAY;AACjB,SAAK,SAAS;AAEd,SAAK,KAAK,gBAAgB;AAAA,MACxB,MAAM,MAAM;AAAA,MACZ,QAAQ,MAAM;AAAA,MACd,UAAU,MAAM;AAAA,IACtB,CAAK;AAGD,QAAI,KAAK,mBAAmB,MAAM,SAAS,KAAM;AAC/C,WAAK,WAAU;AAAA,IACjB;AAAA,EACF;AAAA,EAEA,aAAa;AACX,QAAI,KAAK,qBAAqB,KAAK,sBAAsB;AACvD,WAAK,KAAK,gCAAgC;AAC1C,WAAK,KAAK,oBAAoB,EAAE,UAAU,KAAK,mBAAmB;AAClE;AAAA,IACF;AAEA,SAAK;AACL,UAAM,QAAQ,KAAK,oBAAoB,KAAK,IAAI,KAAK,kBAAkB,KAAK,oBAAoB,CAAC;AAEjG,SAAK,KAAK,mBAAmB,KAAK,eAAe,KAAK,iBAAiB,GAAG;AAC1E,SAAK,KAAK,gBAAgB,EAAE,SAAS,KAAK,mBAAmB,OAAO;AAEpE,SAAK,iBAAiB,WAAW,MAAM;AACrC,UAAI,KAAK,iBAAiB;AACxB,aAAK,QAAO,EAAG,MAAM,SAAO,QAAQ,MAAM,iCAAiC,GAAG,CAAC;AAAA,MACjF;AAAA,IACF,GAAG,KAAK;AAAA,EACV;AAAA,EAEA,kBAAkB;AAChB,QAAI,CAAC,KAAK,aAAc;AAExB,SAAK,YAAY,YAAY,MAAM;AACjC,UAAI,KAAK,aAAa;AACpB,aAAK,KAAK,EAAE,QAAQ,OAAM,CAAE;AAC5B,aAAK,kBAAiB;AAAA,MACxB;AAAA,IACF,GAAG,KAAK,YAAY;AAAA,EACtB;AAAA,EAEA,oBAAoB;AAClB,SAAK,kBAAiB;AAEtB,SAAK,YAAY,WAAW,MAAM;AAChC,cAAQ,KAAK,+CAA+C;AAC5D,UAAI,KAAK,QAAQ;AACf,aAAK,OAAO,MAAM,MAAM,cAAc;AAAA,MACxC;AAAA,IACF,GAAG,KAAK,WAAW;AAAA,EACrB;AAAA,EAEA,oBAAoB;AAClB,QAAI,KAAK,WAAW;AAClB,mBAAa,KAAK,SAAS;AAC3B,WAAK,YAAY;AAAA,IACnB;AAAA,EACF;AAAA,EAEA,eAAe;AACb,QAAI,KAAK,gBAAgB;AACvB,mBAAa,KAAK,cAAc;AAChC,WAAK,iBAAiB;AAAA,IACxB;AACA,QAAI,KAAK,WAAW;AAClB,oBAAc,KAAK,SAAS;AAC5B,WAAK,YAAY;AAAA,IACnB;AACA,SAAK,kBAAiB;AAAA,EACxB;AAAA,EAEA,QAAQ,MAAM;AACZ,QAAI,KAAK,OAAO;AACd,cAAQ,IAAI,eAAe,GAAG,IAAI;AAAA,IACpC;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAiBA,OAAO,UAAU,SAAS,OAAO,iBAAiB;AAChD,QAAI,CAAC,QAAS,OAAM,IAAI,MAAM,qBAAqB;AAGnD,UAAM,MAAM,IAAI,IAAI,OAAO;AAG3B,QAAI,WAAW,IAAI,aAAa,WAAW,SAAS;AAGpD,QAAI,WAAW,KAAK,WAAW,GAAG,IAAI,OAAO,IAAI,IAAI;AAErD,WAAO,IAAI,SAAQ;AAAA,EACrB;AACF;AAGA,OAAO,OAAO,gBAAgB,WAAW,YAAY;"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";const t=require("./Rest-
|
|
2
|
-
//# sourceMappingURL=WebSocketClient-
|
|
1
|
+
"use strict";const t=require("./Rest-DYPLEzNy.js");class WebSocketClient{constructor(t={}){this.url=t.url,this.socket=null,this.isConnected=!1,this.isConnecting=!1,this.getToken=t.getToken||null,this.tokenPrefix=t.tokenPrefix||"bearer",this.shouldReconnect=!1!==t.autoReconnect,this.maxReconnectAttempts=t.maxReconnectAttempts||1/0,this.reconnectInterval=t.reconnectInterval||3e3,this.reconnectBackoff=t.reconnectBackoff||1.5,this.reconnectAttempts=0,this.reconnectTimer=null,this.pingInterval=t.pingInterval||3e4,this.pongTimeout=t.pongTimeout||5e3,this.pingTimer=null,this.pongTimer=null,this.debug=t.debug||!1}async connect(t=null){if(t&&(this.url=t),!this.url)throw new Error("WebSocket URL is required");if(!this.isConnected&&!this.isConnecting)return this.isConnecting=!0,this._log("Connecting to:",this.url),new Promise((t,e)=>{try{this.socket=new WebSocket(this.url),this.socket.onopen=()=>{this._log("Connected"),this.isConnected=!0,this.isConnecting=!1,this.reconnectAttempts=0,this._authenticate(),this._startHeartbeat(),this.emit("connected"),t()},this.socket.onmessage=t=>this._handleMessage(t),this.socket.onerror=t=>this._handleError(t,e),this.socket.onclose=t=>this._handleClose(t)}catch(n){this.isConnecting=!1,e(n)}})}disconnect(){this.shouldReconnect=!1,this._clearTimers(),this.socket&&(this._log("Disconnecting"),this.socket.close(1e3,"Client disconnect"))}send(t){if(!this.isConnected)throw new Error("WebSocket not connected");const e="string"==typeof t?t:JSON.stringify(t);this.socket.send(e),this._log("Sent:",e)}_authenticate(){const t=this.getToken?this.getToken():null;t?this.send({type:"authenticate",token:t,prefix:this.tokenPrefix}):console.warn("[WebSocket] No token available")}_handleMessage(t){let e;this._log("Received:",t.data);try{e=JSON.parse(t.data)}catch(n){e=t.data}"pong"!==e?.type?(e?.type&&this.emit(`message:${e.type}`,e),this.emit("message",e)):this._clearPongTimeout()}_handleError(t,e){console.error("[WebSocket] Error:",t),this.emit("error",t),e&&e(new Error("WebSocket connection failed"))}_handleClose(t){this._log("Closed:",t.code,t.reason),this.isConnected=!1,this.isConnecting=!1,this._clearTimers(),this.socket=null,this.emit("disconnected",{code:t.code,reason:t.reason,wasClean:t.wasClean}),this.shouldReconnect&&1e3!==t.code&&this._reconnect()}_reconnect(){if(this.reconnectAttempts>=this.maxReconnectAttempts)return this._log("Max reconnect attempts reached"),void this.emit("reconnect-failed",{attempts:this.reconnectAttempts});this.reconnectAttempts++;const t=this.reconnectInterval*Math.pow(this.reconnectBackoff,this.reconnectAttempts-1);this._log(`Reconnecting in ${t}ms (attempt ${this.reconnectAttempts})`),this.emit("reconnecting",{attempt:this.reconnectAttempts,delay:t}),this.reconnectTimer=setTimeout(()=>{this.shouldReconnect&&this.connect().catch(t=>console.error("[WebSocket] Reconnect failed:",t))},t)}_startHeartbeat(){this.pingInterval&&(this.pingTimer=setInterval(()=>{this.isConnected&&(this.send({action:"ping"}),this._startPongTimeout())},this.pingInterval))}_startPongTimeout(){this._clearPongTimeout(),this.pongTimer=setTimeout(()=>{console.warn("[WebSocket] Pong timeout - closing connection"),this.socket&&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()}_log(...t){this.debug}static deriveURL(t,e="/ws/realtime/"){if(!t)throw new Error("baseURL is required");const n=new URL(t);return n.protocol="https:"===n.protocol?"wss:":"ws:",n.pathname=e.startsWith("/")?e:`/${e}`,n.toString()}}Object.assign(WebSocketClient.prototype,t.EventEmitter),exports.WebSocketClient=WebSocketClient;
|
|
2
|
+
//# sourceMappingURL=WebSocketClient-Dzwprd15.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"WebSocketClient-sEN2DmCF.js","sources":["../../src/core/services/WebSocketClient.js"],"sourcesContent":["/**\n * WebSocketClient - Simple, robust WebSocket client with auto-reconnect\n *\n * Features:\n * - Auto-reconnect with exponential backoff\n * - Heartbeat ping/pong with timeout disconnect\n * - Event-driven architecture using EventEmitter\n * - Token-based authentication\n *\n * Usage:\n * const ws = new WebSocketClient({\n * url: \"wss://api.example.com/ws/realtime\",\n * tokenPrefix: \"bearer\",\n * getToken: () => app.tokenManager.getToken()\n * });\n *\n * ws.on('connected', () => console.log('Connected!'));\n * ws.on('message', (data) => console.log('Received:', data));\n * ws.connect();\n */\n\nimport EventEmitter from '@core/mixins/EventEmitter.js';\n\nclass WebSocketClient {\n constructor(options = {}) {\n // Connection\n this.url = options.url;\n this.socket = null;\n this.isConnected = false;\n this.isConnecting = false;\n\n // Auth\n this.getToken = options.getToken || null;\n this.tokenPrefix = options.tokenPrefix || 'bearer';\n\n // Reconnection\n this.shouldReconnect = options.autoReconnect !== false;\n this.maxReconnectAttempts = options.maxReconnectAttempts || Infinity;\n this.reconnectInterval = options.reconnectInterval || 3000;\n this.reconnectBackoff = options.reconnectBackoff || 1.5;\n this.reconnectAttempts = 0;\n this.reconnectTimer = null;\n\n // Heartbeat\n this.pingInterval = options.pingInterval || 30000;\n this.pongTimeout = options.pongTimeout || 5000;\n this.pingTimer = null;\n this.pongTimer = null;\n\n // Debug\n this.debug = options.debug || false;\n }\n\n /**\n * Connect to WebSocket server\n */\n async connect(url = null) {\n if (url) this.url = url;\n if (!this.url) throw new Error('WebSocket URL is required');\n if (this.isConnected || this.isConnecting) return;\n\n this.isConnecting = true;\n this._log('Connecting to:', this.url);\n\n return new Promise((resolve, reject) => {\n try {\n this.socket = new WebSocket(this.url);\n\n this.socket.onopen = () => {\n this._log('Connected');\n this.isConnected = true;\n this.isConnecting = false;\n this.reconnectAttempts = 0;\n\n this._authenticate();\n this._startHeartbeat();\n\n this.emit('connected');\n resolve();\n };\n\n this.socket.onmessage = (event) => this._handleMessage(event);\n this.socket.onerror = (event) => this._handleError(event, reject);\n this.socket.onclose = (event) => this._handleClose(event);\n\n } catch (error) {\n this.isConnecting = false;\n reject(error);\n }\n });\n }\n\n /**\n * Disconnect from server\n */\n disconnect() {\n this.shouldReconnect = false;\n this._clearTimers();\n\n if (this.socket) {\n this._log('Disconnecting');\n this.socket.close(1000, 'Client disconnect');\n }\n }\n\n /**\n * Send data (auto-stringifies objects)\n */\n send(data) {\n if (!this.isConnected) {\n throw new Error('WebSocket not connected');\n }\n\n const message = typeof data === 'string' ? data : JSON.stringify(data);\n this.socket.send(message);\n this._log('Sent:', message);\n }\n\n // Private methods\n\n _authenticate() {\n const token = this.getToken ? this.getToken() : null;\n if (!token) {\n console.warn('[WebSocket] No token available');\n return;\n }\n\n this.send({\n type: 'authenticate',\n token,\n prefix: this.tokenPrefix\n });\n }\n\n _handleMessage(event) {\n this._log('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 pong response\n if (data?.type === 'pong') {\n this._clearPongTimeout();\n return;\n }\n\n // Emit specific event types\n if (data?.type) {\n this.emit(`message:${data.type}`, data);\n }\n\n // Always emit generic message event\n this.emit('message', data);\n }\n\n _handleError(event, rejectFn) {\n console.error('[WebSocket] Error:', event);\n this.emit('error', event);\n\n if (rejectFn) {\n rejectFn(new Error('WebSocket connection failed'));\n }\n }\n\n _handleClose(event) {\n this._log('Closed:', event.code, event.reason);\n\n this.isConnected = false;\n this.isConnecting = false;\n this._clearTimers();\n this.socket = null;\n\n this.emit('disconnected', {\n code: event.code,\n reason: event.reason,\n wasClean: event.wasClean\n });\n\n // Auto-reconnect (except for clean closes)\n if (this.shouldReconnect && event.code !== 1000) {\n this._reconnect();\n }\n }\n\n _reconnect() {\n if (this.reconnectAttempts >= this.maxReconnectAttempts) {\n this._log('Max reconnect attempts reached');\n this.emit('reconnect-failed', { attempts: this.reconnectAttempts });\n return;\n }\n\n this.reconnectAttempts++;\n const delay = this.reconnectInterval * Math.pow(this.reconnectBackoff, this.reconnectAttempts - 1);\n\n this._log(`Reconnecting in ${delay}ms (attempt ${this.reconnectAttempts})`);\n this.emit('reconnecting', { attempt: this.reconnectAttempts, delay });\n\n this.reconnectTimer = setTimeout(() => {\n if (this.shouldReconnect) {\n this.connect().catch(err => console.error('[WebSocket] Reconnect failed:', err));\n }\n }, delay);\n }\n\n _startHeartbeat() {\n if (!this.pingInterval) return;\n\n this.pingTimer = setInterval(() => {\n if (this.isConnected) {\n this.send({ action: 'ping' });\n this._startPongTimeout();\n }\n }, this.pingInterval);\n }\n\n _startPongTimeout() {\n this._clearPongTimeout();\n\n this.pongTimer = setTimeout(() => {\n console.warn('[WebSocket] Pong timeout - closing connection');\n if (this.socket) {\n this.socket.close(1006, 'Pong timeout');\n }\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 if (this.pingTimer) {\n clearInterval(this.pingTimer);\n this.pingTimer = null;\n }\n this._clearPongTimeout();\n }\n\n _log(...args) {\n if (this.debug) {\n console.log('[WebSocket]', ...args);\n }\n }\n\n // Static methods\n\n /**\n * Convert REST API base URL to WebSocket URL\n * @param {string} baseURL - REST API base URL (http/https)\n * @param {string} path - WebSocket path (default: '/ws')\n * @returns {string} WebSocket URL (ws/wss)\n *\n * @example\n * WebSocketClient.deriveURL('https://api.example.com', '/ws/realtime')\n * // Returns: 'wss://api.example.com/ws/realtime'\n *\n * WebSocketClient.deriveURL('http://localhost:3000')\n * // Returns: 'ws://localhost:3000/ws'\n */\n static deriveURL(baseURL, path = '/ws/realtime/') {\n if (!baseURL) throw new Error('baseURL is required');\n\n // Parse the base URL\n const url = new URL(baseURL);\n\n // Convert http(s) to ws(s)\n url.protocol = url.protocol === 'https:' ? 'wss:' : 'ws:';\n\n // Set the path (ensure it starts with /)\n url.pathname = path.startsWith('/') ? path : `/${path}`;\n\n return url.toString();\n }\n}\n\n// Add EventEmitter mixin\nObject.assign(WebSocketClient.prototype, EventEmitter);\n\nexport default WebSocketClient;\n"],"names":["WebSocketClient","constructor","options","this","url","socket","isConnected","isConnecting","getToken","tokenPrefix","shouldReconnect","autoReconnect","maxReconnectAttempts","Infinity","reconnectInterval","reconnectBackoff","reconnectAttempts","reconnectTimer","pingInterval","pongTimeout","pingTimer","pongTimer","debug","connect","Error","_log","Promise","resolve","reject","WebSocket","onopen","_authenticate","_startHeartbeat","emit","onmessage","event","_handleMessage","onerror","_handleError","onclose","_handleClose","error","disconnect","_clearTimers","close","send","data","message","JSON","stringify","token","type","prefix","console","warn","parse","_clearPongTimeout","rejectFn","code","reason","wasClean","_reconnect","attempts","delay","Math","pow","attempt","setTimeout","catch","err","setInterval","action","_startPongTimeout","clearTimeout","clearInterval","args","deriveURL","baseURL","path","URL","protocol","pathname","startsWith","toString","Object","assign","prototype","EventEmitter"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"WebSocketClient-Dzwprd15.js","sources":["../../src/core/services/WebSocketClient.js"],"sourcesContent":["/**\n * WebSocketClient - Simple, robust WebSocket client with auto-reconnect\n *\n * Features:\n * - Auto-reconnect with exponential backoff\n * - Heartbeat ping/pong with timeout disconnect\n * - Event-driven architecture using EventEmitter\n * - Token-based authentication\n *\n * Usage:\n * const ws = new WebSocketClient({\n * url: \"wss://api.example.com/ws/realtime\",\n * tokenPrefix: \"bearer\",\n * getToken: () => app.tokenManager.getToken()\n * });\n *\n * ws.on('connected', () => console.log('Connected!'));\n * ws.on('message', (data) => console.log('Received:', data));\n * ws.connect();\n */\n\nimport EventEmitter from '@core/mixins/EventEmitter.js';\n\nclass WebSocketClient {\n constructor(options = {}) {\n // Connection\n this.url = options.url;\n this.socket = null;\n this.isConnected = false;\n this.isConnecting = false;\n\n // Auth\n this.getToken = options.getToken || null;\n this.tokenPrefix = options.tokenPrefix || 'bearer';\n\n // Reconnection\n this.shouldReconnect = options.autoReconnect !== false;\n this.maxReconnectAttempts = options.maxReconnectAttempts || Infinity;\n this.reconnectInterval = options.reconnectInterval || 3000;\n this.reconnectBackoff = options.reconnectBackoff || 1.5;\n this.reconnectAttempts = 0;\n this.reconnectTimer = null;\n\n // Heartbeat\n this.pingInterval = options.pingInterval || 30000;\n this.pongTimeout = options.pongTimeout || 5000;\n this.pingTimer = null;\n this.pongTimer = null;\n\n // Debug\n this.debug = options.debug || false;\n }\n\n /**\n * Connect to WebSocket server\n */\n async connect(url = null) {\n if (url) this.url = url;\n if (!this.url) throw new Error('WebSocket URL is required');\n if (this.isConnected || this.isConnecting) return;\n\n this.isConnecting = true;\n this._log('Connecting to:', this.url);\n\n return new Promise((resolve, reject) => {\n try {\n this.socket = new WebSocket(this.url);\n\n this.socket.onopen = () => {\n this._log('Connected');\n this.isConnected = true;\n this.isConnecting = false;\n this.reconnectAttempts = 0;\n\n this._authenticate();\n this._startHeartbeat();\n\n this.emit('connected');\n resolve();\n };\n\n this.socket.onmessage = (event) => this._handleMessage(event);\n this.socket.onerror = (event) => this._handleError(event, reject);\n this.socket.onclose = (event) => this._handleClose(event);\n\n } catch (error) {\n this.isConnecting = false;\n reject(error);\n }\n });\n }\n\n /**\n * Disconnect from server\n */\n disconnect() {\n this.shouldReconnect = false;\n this._clearTimers();\n\n if (this.socket) {\n this._log('Disconnecting');\n this.socket.close(1000, 'Client disconnect');\n }\n }\n\n /**\n * Send data (auto-stringifies objects)\n */\n send(data) {\n if (!this.isConnected) {\n throw new Error('WebSocket not connected');\n }\n\n const message = typeof data === 'string' ? data : JSON.stringify(data);\n this.socket.send(message);\n this._log('Sent:', message);\n }\n\n // Private methods\n\n _authenticate() {\n const token = this.getToken ? this.getToken() : null;\n if (!token) {\n console.warn('[WebSocket] No token available');\n return;\n }\n\n this.send({\n type: 'authenticate',\n token,\n prefix: this.tokenPrefix\n });\n }\n\n _handleMessage(event) {\n this._log('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 pong response\n if (data?.type === 'pong') {\n this._clearPongTimeout();\n return;\n }\n\n // Emit specific event types\n if (data?.type) {\n this.emit(`message:${data.type}`, data);\n }\n\n // Always emit generic message event\n this.emit('message', data);\n }\n\n _handleError(event, rejectFn) {\n console.error('[WebSocket] Error:', event);\n this.emit('error', event);\n\n if (rejectFn) {\n rejectFn(new Error('WebSocket connection failed'));\n }\n }\n\n _handleClose(event) {\n this._log('Closed:', event.code, event.reason);\n\n this.isConnected = false;\n this.isConnecting = false;\n this._clearTimers();\n this.socket = null;\n\n this.emit('disconnected', {\n code: event.code,\n reason: event.reason,\n wasClean: event.wasClean\n });\n\n // Auto-reconnect (except for clean closes)\n if (this.shouldReconnect && event.code !== 1000) {\n this._reconnect();\n }\n }\n\n _reconnect() {\n if (this.reconnectAttempts >= this.maxReconnectAttempts) {\n this._log('Max reconnect attempts reached');\n this.emit('reconnect-failed', { attempts: this.reconnectAttempts });\n return;\n }\n\n this.reconnectAttempts++;\n const delay = this.reconnectInterval * Math.pow(this.reconnectBackoff, this.reconnectAttempts - 1);\n\n this._log(`Reconnecting in ${delay}ms (attempt ${this.reconnectAttempts})`);\n this.emit('reconnecting', { attempt: this.reconnectAttempts, delay });\n\n this.reconnectTimer = setTimeout(() => {\n if (this.shouldReconnect) {\n this.connect().catch(err => console.error('[WebSocket] Reconnect failed:', err));\n }\n }, delay);\n }\n\n _startHeartbeat() {\n if (!this.pingInterval) return;\n\n this.pingTimer = setInterval(() => {\n if (this.isConnected) {\n this.send({ action: 'ping' });\n this._startPongTimeout();\n }\n }, this.pingInterval);\n }\n\n _startPongTimeout() {\n this._clearPongTimeout();\n\n this.pongTimer = setTimeout(() => {\n console.warn('[WebSocket] Pong timeout - closing connection');\n if (this.socket) {\n this.socket.close(1006, 'Pong timeout');\n }\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 if (this.pingTimer) {\n clearInterval(this.pingTimer);\n this.pingTimer = null;\n }\n this._clearPongTimeout();\n }\n\n _log(...args) {\n if (this.debug) {\n console.log('[WebSocket]', ...args);\n }\n }\n\n // Static methods\n\n /**\n * Convert REST API base URL to WebSocket URL\n * @param {string} baseURL - REST API base URL (http/https)\n * @param {string} path - WebSocket path (default: '/ws')\n * @returns {string} WebSocket URL (ws/wss)\n *\n * @example\n * WebSocketClient.deriveURL('https://api.example.com', '/ws/realtime')\n * // Returns: 'wss://api.example.com/ws/realtime'\n *\n * WebSocketClient.deriveURL('http://localhost:3000')\n * // Returns: 'ws://localhost:3000/ws'\n */\n static deriveURL(baseURL, path = '/ws/realtime/') {\n if (!baseURL) throw new Error('baseURL is required');\n\n // Parse the base URL\n const url = new URL(baseURL);\n\n // Convert http(s) to ws(s)\n url.protocol = url.protocol === 'https:' ? 'wss:' : 'ws:';\n\n // Set the path (ensure it starts with /)\n url.pathname = path.startsWith('/') ? path : `/${path}`;\n\n return url.toString();\n }\n}\n\n// Add EventEmitter mixin\nObject.assign(WebSocketClient.prototype, EventEmitter);\n\nexport default WebSocketClient;\n"],"names":["WebSocketClient","constructor","options","this","url","socket","isConnected","isConnecting","getToken","tokenPrefix","shouldReconnect","autoReconnect","maxReconnectAttempts","Infinity","reconnectInterval","reconnectBackoff","reconnectAttempts","reconnectTimer","pingInterval","pongTimeout","pingTimer","pongTimer","debug","connect","Error","_log","Promise","resolve","reject","WebSocket","onopen","_authenticate","_startHeartbeat","emit","onmessage","event","_handleMessage","onerror","_handleError","onclose","_handleClose","error","disconnect","_clearTimers","close","send","data","message","JSON","stringify","token","type","prefix","console","warn","parse","_clearPongTimeout","rejectFn","code","reason","wasClean","_reconnect","attempts","delay","Math","pow","attempt","setTimeout","catch","err","setInterval","action","_startPongTimeout","clearTimeout","clearInterval","args","deriveURL","baseURL","path","URL","protocol","pathname","startsWith","toString","Object","assign","prototype","EventEmitter"],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";const O="2.1.
|
|
2
|
-
//# sourceMappingURL=version-
|
|
1
|
+
"use strict";const O="2.1.1110",o="2025-11-28T17:43:02.016Z",i={full:O,major:2,minor:1,revision:1110,buildTime:o,toString(){return this.full},compare(O){const o=O=>O.split(".").map(Number),[i,r,t]=o(this.full),[e,n,s]=o(O);return i!==e?i-e:r!==n?r-n:t-s}};"undefined"!=typeof window&&(window.MOJO=window.MOJO||{},window.MOJO.VERSION=O,window.MOJO.VERSION_INFO=i,window.MOJO.version=O),exports.BUILD_TIME=o,exports.VERSION=O,exports.VERSION_INFO=i,exports.VERSION_MAJOR=2,exports.VERSION_MINOR=1,exports.VERSION_REVISION=1110;
|
|
2
|
+
//# sourceMappingURL=version-C5lFa1F0.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"version-
|
|
1
|
+
{"version":3,"file":"version-C5lFa1F0.js","sources":["../../src/version.js"],"sourcesContent":["/**\n * MOJO Framework Version Information\n * Auto-generated on 2025-11-28T17:43:02.016Z\n */\n\nexport const VERSION = '2.1.1110';\nexport const VERSION_MAJOR = 2;\nexport const VERSION_MINOR = 1;\nexport const VERSION_REVISION = 1110;\nexport const BUILD_TIME = '2025-11-28T17:43:02.016Z';\n\n// Version object for easy access\nexport const VERSION_INFO = {\n full: VERSION,\n major: VERSION_MAJOR,\n minor: VERSION_MINOR,\n revision: VERSION_REVISION,\n buildTime: BUILD_TIME,\n toString() {\n return this.full;\n },\n compare(other) {\n const parseVer = (v) => v.split('.').map(Number);\n const [a1, a2, a3] = parseVer(this.full);\n const [b1, b2, b3] = parseVer(other);\n\n if (a1 !== b1) return a1 - b1;\n if (a2 !== b2) return a2 - b2;\n return a3 - b3;\n }\n};\n\n// Make version globally available if in browser\nif (typeof window !== 'undefined') {\n window.MOJO = window.MOJO || {};\n window.MOJO.VERSION = VERSION;\n window.MOJO.VERSION_INFO = VERSION_INFO;\n\n // Also add to MOJO.version for convenience\n window.MOJO.version = VERSION;\n}\n\nexport default VERSION_INFO;\n"],"names":["VERSION","BUILD_TIME","VERSION_INFO","full","major","minor","revision","buildTime","toString","this","compare","other","parseVer","v","split","map","Number","a1","a2","a3","b1","b2","b3","window","MOJO","version"],"mappings":"aAKY,MAACA,EAAU,WAIVC,EAAa,2BAGbC,EAAe,CACxBC,KAAMH,EACNI,MARyB,EASzBC,MARyB,EASzBC,SAR4B,KAS5BC,UAAWN,EACX,QAAAO,GACI,OAAOC,KAAKN,IAChB,EACA,OAAAO,CAAQC,GACJ,MAAMC,EAAYC,GAAMA,EAAEC,MAAM,KAAKC,IAAIC,SAClCC,EAAIC,EAAIC,GAAMP,EAASH,KAAKN,OAC5BiB,EAAIC,EAAIC,GAAMV,EAASD,GAE9B,OAAIM,IAAOG,EAAWH,EAAKG,EACvBF,IAAOG,EAAWH,EAAKG,EACpBF,EAAKG,CAChB,GAIkB,oBAAXC,SACPA,OAAOC,KAAOD,OAAOC,MAAQ,CAAA,EAC7BD,OAAOC,KAAKxB,QAAUA,EACtBuB,OAAOC,KAAKtB,aAAeA,EAG3BqB,OAAOC,KAAKC,QAAUzB,uFAjCG,wBACA,2BACG"}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
const VERSION = "2.1.
|
|
1
|
+
const VERSION = "2.1.1110";
|
|
2
2
|
const VERSION_MAJOR = 2;
|
|
3
3
|
const VERSION_MINOR = 1;
|
|
4
|
-
const VERSION_REVISION =
|
|
5
|
-
const BUILD_TIME = "2025-11-
|
|
4
|
+
const VERSION_REVISION = 1110;
|
|
5
|
+
const BUILD_TIME = "2025-11-28T17:43:02.016Z";
|
|
6
6
|
const VERSION_INFO = {
|
|
7
7
|
full: VERSION,
|
|
8
8
|
major: VERSION_MAJOR,
|
|
@@ -35,4 +35,4 @@ export {
|
|
|
35
35
|
VERSION_MINOR as c,
|
|
36
36
|
VERSION_REVISION as d
|
|
37
37
|
};
|
|
38
|
-
//# sourceMappingURL=version-
|
|
38
|
+
//# sourceMappingURL=version-FRgkiWti.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"version-
|
|
1
|
+
{"version":3,"file":"version-FRgkiWti.js","sources":["../../src/version.js"],"sourcesContent":["/**\n * MOJO Framework Version Information\n * Auto-generated on 2025-11-28T17:43:02.016Z\n */\n\nexport const VERSION = '2.1.1110';\nexport const VERSION_MAJOR = 2;\nexport const VERSION_MINOR = 1;\nexport const VERSION_REVISION = 1110;\nexport const BUILD_TIME = '2025-11-28T17:43:02.016Z';\n\n// Version object for easy access\nexport const VERSION_INFO = {\n full: VERSION,\n major: VERSION_MAJOR,\n minor: VERSION_MINOR,\n revision: VERSION_REVISION,\n buildTime: BUILD_TIME,\n toString() {\n return this.full;\n },\n compare(other) {\n const parseVer = (v) => v.split('.').map(Number);\n const [a1, a2, a3] = parseVer(this.full);\n const [b1, b2, b3] = parseVer(other);\n\n if (a1 !== b1) return a1 - b1;\n if (a2 !== b2) return a2 - b2;\n return a3 - b3;\n }\n};\n\n// Make version globally available if in browser\nif (typeof window !== 'undefined') {\n window.MOJO = window.MOJO || {};\n window.MOJO.VERSION = VERSION;\n window.MOJO.VERSION_INFO = VERSION_INFO;\n\n // Also add to MOJO.version for convenience\n window.MOJO.version = VERSION;\n}\n\nexport default VERSION_INFO;\n"],"names":[],"mappings":"AAKY,MAAC,UAAU;AACX,MAAC,gBAAgB;AACjB,MAAC,gBAAgB;AACjB,MAAC,mBAAmB;AACpB,MAAC,aAAa;AAGd,MAAC,eAAe;AAAA,EACxB,MAAM;AAAA,EACN,OAAO;AAAA,EACP,OAAO;AAAA,EACP,UAAU;AAAA,EACV,WAAW;AAAA,EACX,WAAW;AACP,WAAO,KAAK;AAAA,EAChB;AAAA,EACA,QAAQ,OAAO;AACX,UAAM,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,EAAE,IAAI,MAAM;AAC/C,UAAM,CAAC,IAAI,IAAI,EAAE,IAAI,SAAS,KAAK,IAAI;AACvC,UAAM,CAAC,IAAI,IAAI,EAAE,IAAI,SAAS,KAAK;AAEnC,QAAI,OAAO,GAAI,QAAO,KAAK;AAC3B,QAAI,OAAO,GAAI,QAAO,KAAK;AAC3B,WAAO,KAAK;AAAA,EAChB;AACJ;AAGA,IAAI,OAAO,WAAW,aAAa;AAC/B,SAAO,OAAO,OAAO,QAAQ,CAAA;AAC7B,SAAO,KAAK,UAAU;AACtB,SAAO,KAAK,eAAe;AAG3B,SAAO,KAAK,UAAU;AAC1B;"}
|
package/dist/core.css
CHANGED
|
@@ -1764,32 +1764,34 @@
|
|
|
1764
1764
|
GroupSearchView - Hierarchical Tree Styles
|
|
1765
1765
|
============================================ */
|
|
1766
1766
|
|
|
1767
|
+
/* Hide chevron in group search - it's a nav tree, not a menu */
|
|
1768
|
+
.group-search-view .bi-chevron-right {
|
|
1769
|
+
display: none !important;
|
|
1770
|
+
}
|
|
1771
|
+
|
|
1772
|
+
/* Tree item wrapper - flat list with visual hierarchy */
|
|
1767
1773
|
.group-search-view .tree-item-wrapper {
|
|
1768
1774
|
display: flex;
|
|
1769
1775
|
align-items: center;
|
|
1770
1776
|
position: relative;
|
|
1771
1777
|
}
|
|
1772
1778
|
|
|
1773
|
-
|
|
1774
|
-
|
|
1779
|
+
/* Container for tree line segments */
|
|
1780
|
+
.group-search-view .tree-lines {
|
|
1781
|
+
display: flex;
|
|
1775
1782
|
flex-shrink: 0;
|
|
1776
1783
|
align-self: stretch;
|
|
1777
1784
|
}
|
|
1778
1785
|
|
|
1779
|
-
|
|
1780
|
-
.group-search-view .tree-
|
|
1781
|
-
|
|
1782
|
-
|
|
1783
|
-
|
|
1784
|
-
bottom: 0;
|
|
1785
|
-
width: 100%;
|
|
1786
|
-
height: 100%;
|
|
1787
|
-
display: block;
|
|
1788
|
-
pointer-events: none;
|
|
1786
|
+
/* Each segment is a fixed width column */
|
|
1787
|
+
.group-search-view .tree-seg {
|
|
1788
|
+
width: 24px;
|
|
1789
|
+
position: relative;
|
|
1790
|
+
align-self: stretch;
|
|
1789
1791
|
}
|
|
1790
1792
|
|
|
1791
|
-
/* Vertical line
|
|
1792
|
-
.group-search-view .tree-
|
|
1793
|
+
/* Vertical line segment - continues through (for ancestors that aren't last) */
|
|
1794
|
+
.group-search-view .tree-seg-vert::before {
|
|
1793
1795
|
content: "";
|
|
1794
1796
|
position: absolute;
|
|
1795
1797
|
left: 12px;
|
|
@@ -1799,7 +1801,8 @@
|
|
|
1799
1801
|
background: var(--bs-border-color);
|
|
1800
1802
|
}
|
|
1801
1803
|
|
|
1802
|
-
|
|
1804
|
+
/* Vertical line segment ending - only draws top half (for last item in branch) */
|
|
1805
|
+
.group-search-view .tree-seg-vert-end::before {
|
|
1803
1806
|
content: "";
|
|
1804
1807
|
position: absolute;
|
|
1805
1808
|
left: 12px;
|
|
@@ -1809,49 +1812,59 @@
|
|
|
1809
1812
|
background: var(--bs-border-color);
|
|
1810
1813
|
}
|
|
1811
1814
|
|
|
1812
|
-
/*
|
|
1813
|
-
.group-search-view .tree-
|
|
1814
|
-
|
|
1815
|
+
/* Middle segment - vertical line full height + horizontal branch */
|
|
1816
|
+
.group-search-view .tree-seg-mid::before {
|
|
1817
|
+
content: "";
|
|
1818
|
+
position: absolute;
|
|
1819
|
+
left: 12px;
|
|
1820
|
+
top: 0;
|
|
1821
|
+
bottom: 0;
|
|
1822
|
+
width: 2px;
|
|
1823
|
+
background: var(--bs-border-color);
|
|
1824
|
+
}
|
|
1825
|
+
.group-search-view .tree-seg-mid::after {
|
|
1815
1826
|
content: "";
|
|
1816
1827
|
position: absolute;
|
|
1817
1828
|
left: 12px;
|
|
1818
1829
|
top: 50%;
|
|
1819
|
-
width:
|
|
1830
|
+
width: 12px;
|
|
1820
1831
|
height: 2px;
|
|
1821
1832
|
background: var(--bs-border-color);
|
|
1822
1833
|
}
|
|
1823
1834
|
|
|
1824
|
-
|
|
1825
|
-
|
|
1826
|
-
|
|
1827
|
-
|
|
1828
|
-
|
|
1829
|
-
|
|
1835
|
+
/* Last segment - vertical line stops at middle + horizontal branch */
|
|
1836
|
+
.group-search-view .tree-seg-last::before {
|
|
1837
|
+
content: "";
|
|
1838
|
+
position: absolute;
|
|
1839
|
+
left: 12px;
|
|
1840
|
+
top: 0;
|
|
1841
|
+
height: 50%;
|
|
1842
|
+
width: 2px;
|
|
1843
|
+
background: var(--bs-border-color);
|
|
1830
1844
|
}
|
|
1831
|
-
|
|
1832
|
-
|
|
1833
|
-
|
|
1834
|
-
|
|
1835
|
-
|
|
1836
|
-
|
|
1837
|
-
|
|
1838
|
-
|
|
1839
|
-
align-items: center;
|
|
1840
|
-
justify-content: center;
|
|
1841
|
-
transition: color 0.15s ease;
|
|
1845
|
+
.group-search-view .tree-seg-last::after {
|
|
1846
|
+
content: "";
|
|
1847
|
+
position: absolute;
|
|
1848
|
+
left: 12px;
|
|
1849
|
+
top: 50%;
|
|
1850
|
+
width: 12px;
|
|
1851
|
+
height: 2px;
|
|
1852
|
+
background: var(--bs-border-color);
|
|
1842
1853
|
}
|
|
1843
1854
|
|
|
1844
|
-
|
|
1845
|
-
|
|
1855
|
+
/* Bold text for parents with children */
|
|
1856
|
+
.group-search-view .tree-item-wrapper.has-children .tree-item-name {
|
|
1857
|
+
font-weight: 600;
|
|
1846
1858
|
}
|
|
1847
1859
|
|
|
1848
|
-
|
|
1849
|
-
|
|
1860
|
+
/* Hover state - highlight text */
|
|
1861
|
+
.group-search-view .simple-search-item:hover .tree-item-name {
|
|
1862
|
+
color: var(--bs-primary);
|
|
1850
1863
|
}
|
|
1851
1864
|
|
|
1852
|
-
.group-search-view .tree-
|
|
1853
|
-
|
|
1854
|
-
|
|
1865
|
+
.group-search-view .simple-search-item:hover .tree-item-kind {
|
|
1866
|
+
background: var(--bs-primary);
|
|
1867
|
+
color: white;
|
|
1855
1868
|
}
|
|
1856
1869
|
|
|
1857
1870
|
.group-search-view .tree-item-body {
|
|
@@ -1890,16 +1903,9 @@
|
|
|
1890
1903
|
.group-search-view .simple-search-item {
|
|
1891
1904
|
cursor: pointer;
|
|
1892
1905
|
transition: background-color 0.15s ease;
|
|
1906
|
+
/*border: 1px dotted #efefef;*/
|
|
1893
1907
|
}
|
|
1894
1908
|
|
|
1895
1909
|
.group-search-view .simple-search-item:hover {
|
|
1896
|
-
background-color: var(--bs-
|
|
1897
|
-
}
|
|
1898
|
-
|
|
1899
|
-
.group-search-view .simple-search-item .bi-chevron-right {
|
|
1900
|
-
opacity: 0.5;
|
|
1901
|
-
}
|
|
1902
|
-
|
|
1903
|
-
.group-search-view .simple-search-item:hover .bi-chevron-right {
|
|
1904
|
-
opacity: 1;
|
|
1910
|
+
background-color: var(--bs-light);
|
|
1905
1911
|
}
|