SHiNE-server/shine-UI/js/services/server-health-service.js

119 lines
3.1 KiB
JavaScript

function normalizeUrl(value) {
return String(value || '').trim();
}
function normalizeShineWsUrl(rawUrl) {
const value = normalizeUrl(rawUrl);
if (!value) return '';
if (value.startsWith('ws://') || value.startsWith('wss://')) {
try {
const parsed = new URL(value);
if (!parsed.pathname || parsed.pathname === '/') parsed.pathname = '/ws';
return parsed.toString();
} catch {
return value;
}
}
if (value.startsWith('http://') || value.startsWith('https://')) {
try {
const parsed = new URL(value);
parsed.protocol = parsed.protocol === 'https:' ? 'wss:' : 'ws:';
if (!parsed.pathname || parsed.pathname === '/') parsed.pathname = '/ws';
return parsed.toString();
} catch {
return `${value.replace(/^http/, 'ws').replace(/\/$/, '')}/ws`;
}
}
return value;
}
async function checkSolanaRpc(url) {
const endpoint = normalizeUrl(url);
if (!endpoint) return false;
try {
const resp = await fetch(endpoint, {
method: 'POST',
cache: 'no-store',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
jsonrpc: '2.0',
id: 1,
method: 'getVersion',
}),
});
if (!resp.ok) return false;
const json = await resp.json();
return Boolean(json?.result?.['solana-core'] || json?.result);
} catch {
return false;
}
}
async function checkArweave(url) {
const base = normalizeUrl(url).replace(/\/+$/, '');
if (!base) return false;
try {
const resp = await fetch(`${base}/info`, { method: 'GET', cache: 'no-store' });
if (!resp.ok) return false;
const json = await resp.json();
return Boolean(json?.network);
} catch {
return false;
}
}
function checkShineWs(url, timeoutMs = 7000) {
const wsUrl = normalizeShineWsUrl(url);
if (!wsUrl) return Promise.resolve(false);
return new Promise((resolve) => {
let done = false;
const finish = (ok) => {
if (done) return;
done = true;
window.clearTimeout(timer);
try { ws.close(); } catch {}
resolve(Boolean(ok));
};
const timer = window.setTimeout(() => finish(false), timeoutMs);
let ws;
try {
ws = new WebSocket(wsUrl);
} catch {
finish(false);
return;
}
ws.addEventListener('open', () => {
try {
ws.send(JSON.stringify({
op: 'Ping',
requestId: `check-${Date.now()}`,
payload: { ts: Date.now() },
}));
} catch {
finish(false);
}
}, { once: true });
ws.addEventListener('message', () => finish(true), { once: true });
ws.addEventListener('error', () => finish(false), { once: true });
ws.addEventListener('close', () => finish(false), { once: true });
});
}
export async function checkServerAvailabilityByKey(key, url) {
if (key === 'solanaServer') {
return (await checkSolanaRpc(url)) ? 'available' : 'unavailable';
}
if (key === 'shineServer') {
return (await checkShineWs(url)) ? 'available' : 'unavailable';
}
if (key === 'arweaveServer') {
return (await checkArweave(url)) ? 'available' : 'unavailable';
}
return 'unavailable';
}