Files
panel-vue/src/composables/useWsMonitor.js
2026-07-14 14:50:48 -06:00

170 lines
4.1 KiB
JavaScript

import { computed, ref } from 'vue'
import { createWsClient } from '../services/wsService'
import { getAuthSession } from '../services/auth'
const DEFAULT_MAX_HISTORY = 200
const logs = ref([])
const connectionStatus = ref('offline')
const connectionDetail = ref('')
const maxHistory = ref(DEFAULT_MAX_HISTORY)
const username = ref('')
const isConnected = computed(() => connectionStatus.value === 'open')
let client = null
function stringifyPayload(payload) {
if (typeof payload === 'string') {
return payload
}
try {
return JSON.stringify(payload)
} catch {
return String(payload)
}
}
const appendLog = (entry) => {
const normalized = {
id: `${Date.now()}_${Math.random().toString(16).slice(2)}`,
timestamp: new Date().toISOString(),
type: entry.type,
label: entry.label,
payload: stringifyPayload(entry.payload),
}
logs.value.unshift(normalized)
if (logs.value.length > maxHistory.value) {
logs.value.length = maxHistory.value
}
}
const ensureClient = () => {
if (client) {
return true
}
const session = getAuthSession()
const token = session?.access_token
if (!token) {
appendLog({
type: 'error',
label: 'No hay token de sesion para conectar WS.',
payload: 'Inicia sesion nuevamente.',
})
return false
}
client = createWsClient({
token,
username: session?.usuario,
onStatus: ({ status, detail }) => {
connectionStatus.value = status
connectionDetail.value = detail
const isErrorLike = ['error', 'failed'].includes(status)
appendLog({
type: isErrorLike ? 'error' : 'status',
label: `Estado: ${status}`,
payload: detail || '-',
})
},
onSend: ({ message, sent }) => {
appendLog({
type: 'outgoing',
label: sent ? 'Solicitud enviada' : 'Solicitud en cola',
payload: message,
})
},
onMessage: (message) => {
appendLog({
type: 'incoming',
label: 'Respuesta recibida',
payload: message,
})
},
})
username.value = client.getUsername()
return true
}
export function useWsMonitor(initialMaxHistory = DEFAULT_MAX_HISTORY) {
if (initialMaxHistory > maxHistory.value) {
maxHistory.value = initialMaxHistory
}
const connect = () => {
const ready = ensureClient()
if (!ready) {
return
}
client.connect()
}
const disconnect = () => {
if (!client) {
connectionStatus.value = 'offline'
connectionDetail.value = ''
return
}
client.disconnect()
client = null
connectionStatus.value = 'offline'
connectionDetail.value = ''
username.value = ''
}
// Envía un mensaje de texto sin envolver al servidor WebSocket. Si el socket no está abierto, el mensaje se encola para enviarse cuando se abra la conexión.
const sendRaw = (message) => {
if (!ensureClient()) {
return
}
client.sendRaw(message)
}
// Envía un comando al servidor WebSocket. El comando se envía como un objeto JSON con la propiedad "command" y cualquier otra propiedad adicional que se pase en "extra".
const sendCommand = (cmd, extra = {}) => {
// Verifica si el cliente WS está inicializado y listo para enviar comandos. Si no lo está, intenta inicializarlo.
if (!ensureClient()) {
return
}
// en este caso, el payload se envía como un objeto con la propiedad "command" y cualquier otra propiedad adicional que se pase en "extra"
client.sendCommand(cmd, extra)
}
const clearLogs = () => {
logs.value = []
}
const setMaxHistory = (nextValue) => {
const normalized = Number(nextValue)
if (Number.isNaN(normalized) || normalized < 20) {
maxHistory.value = 20
} else if (normalized > 1000) {
maxHistory.value = 1000
} else {
maxHistory.value = normalized
}
if (logs.value.length > maxHistory.value) {
logs.value.length = maxHistory.value
}
}
return {
logs,
connectionStatus,
connectionDetail,
isConnected,
maxHistory,
username,
connect,
disconnect,
sendRaw,
sendCommand,
clearLogs,
setMaxHistory,
}
}