mirror of
https://github.com/logos-blockchain/logos-blockchain-block-explorer-template.git
synced 2026-01-02 13:13:10 +00:00
106 lines
3.1 KiB
JavaScript
106 lines
3.1 KiB
JavaScript
export const isBenignStreamError = (error, signal) => {
|
|
return false;
|
|
};
|
|
|
|
export const withBenignFilter = (onError, signal) => (error) => {
|
|
if (!isBenignStreamError(error, signal)) onError?.(error);
|
|
};
|
|
|
|
export async function streamNdjson(url, handleItem, { signal, onError = () => {} } = {}) {
|
|
const response = await fetch(url, {
|
|
headers: { accept: 'application/x-ndjson' },
|
|
signal,
|
|
cache: 'no-cache',
|
|
});
|
|
|
|
if (!response.ok || !response.body) {
|
|
throw new Error(`Stream failed: ${response.status}`);
|
|
}
|
|
|
|
const responseBodyReader = response.body.getReader();
|
|
const textDecoder = new TextDecoder();
|
|
let buffer = '';
|
|
|
|
while (true) {
|
|
let chunk;
|
|
try {
|
|
chunk = await responseBodyReader.read();
|
|
} catch (error) {
|
|
if (signal?.aborted) return;
|
|
onError(error);
|
|
break;
|
|
}
|
|
const { value, done } = chunk;
|
|
if (done) break;
|
|
|
|
buffer += textDecoder.decode(value, { stream: true });
|
|
|
|
let newlineIndex;
|
|
while ((newlineIndex = buffer.indexOf('\n')) >= 0) {
|
|
const line = buffer.slice(0, newlineIndex).trim();
|
|
buffer = buffer.slice(newlineIndex + 1);
|
|
if (!line) continue;
|
|
try {
|
|
handleItem(JSON.parse(line));
|
|
} catch (error) {
|
|
onError(error);
|
|
}
|
|
}
|
|
}
|
|
|
|
const trailing = buffer.trim();
|
|
if (trailing) {
|
|
try {
|
|
handleItem(JSON.parse(trailing));
|
|
} catch (error) {
|
|
onError(error);
|
|
}
|
|
}
|
|
}
|
|
|
|
export const shortenHex = (hexString, left = 10, right = 8) => {
|
|
if (!hexString) return '';
|
|
return hexString.length <= left + right + 1 ? hexString : `${hexString.slice(0, left)}…${hexString.slice(-right)}`;
|
|
};
|
|
|
|
export function formatTimestamp(timestamp) {
|
|
if (timestamp == null) return '';
|
|
const date =
|
|
typeof timestamp === 'number' ? new Date(timestamp < 1e12 ? timestamp * 1000 : timestamp) : new Date(timestamp);
|
|
|
|
if (Number.isNaN(date.getTime())) return '';
|
|
return date.toLocaleString(undefined, {
|
|
year: 'numeric',
|
|
month: '2-digit',
|
|
day: '2-digit',
|
|
hour: '2-digit',
|
|
minute: '2-digit',
|
|
second: '2-digit',
|
|
});
|
|
}
|
|
|
|
export function ensureFixedRowCount(tableBody, columnCount, targetRowCount) {
|
|
// remove existing placeholder rows
|
|
for (let i = tableBody.rows.length - 1; i >= 0; i--) {
|
|
if (tableBody.rows[i].classList.contains('ph')) tableBody.deleteRow(i);
|
|
}
|
|
|
|
// count non-placeholder rows
|
|
let realRowCount = 0;
|
|
for (const row of tableBody.rows) {
|
|
if (!row.classList.contains('ph')) realRowCount++;
|
|
}
|
|
|
|
// append placeholders to reach target count
|
|
for (let i = 0; i < targetRowCount - realRowCount; i++) {
|
|
const tr = document.createElement('tr');
|
|
tr.className = 'ph';
|
|
for (let c = 0; c < columnCount; c++) {
|
|
const td = document.createElement('td');
|
|
td.innerHTML = ' ';
|
|
tr.appendChild(td);
|
|
}
|
|
tableBody.appendChild(tr);
|
|
}
|
|
}
|