All checks were successful
deploy / deploy (push) Successful in 57s
Proof: DB-backed quote lifecycle retention policy, rollup-before-prune maintenance, dashboard storage visibility, and regression tests for preservation and fail-closed behavior. Assumptions: Completed quote outcome attribution remains the current durable successful-trade evidence; venue-native terminal fill ids and fee-complete PnL remain unavailable. Still fake: Historical non-success detail already pruned cannot be recovered; rollups are aggregate analytics, not per-quote settled trade proof.
91 lines
2.8 KiB
JavaScript
91 lines
2.8 KiB
JavaScript
export function formatBoolean(value) {
|
|
if (value == null) return 'Unknown';
|
|
return value ? 'Yes' : 'No';
|
|
}
|
|
|
|
export function formatTimestamp(value) {
|
|
if (!value) return 'Unavailable';
|
|
const date = new Date(value);
|
|
if (Number.isNaN(date.getTime())) return 'Unavailable';
|
|
return date.toLocaleString();
|
|
}
|
|
|
|
export function formatAge(value) {
|
|
if (value == null) return 'Unavailable';
|
|
const numeric = Number(value);
|
|
if (!Number.isFinite(numeric)) return 'Unavailable';
|
|
const ageMs = Math.max(0, Math.floor(numeric));
|
|
if (ageMs < 1000) return `${ageMs} ms`;
|
|
|
|
const seconds = Math.floor(ageMs / 1000);
|
|
if (seconds < 60) return `${seconds}s`;
|
|
|
|
const minutes = Math.floor(seconds / 60);
|
|
const remainingSeconds = seconds % 60;
|
|
if (minutes < 60) {
|
|
return remainingSeconds > 0 ? `${minutes}m ${remainingSeconds}s` : `${minutes}m`;
|
|
}
|
|
|
|
const hours = Math.floor(minutes / 60);
|
|
const remainingMinutes = minutes % 60;
|
|
if (hours < 24) {
|
|
return remainingMinutes > 0 ? `${hours}h ${remainingMinutes}m` : `${hours}h`;
|
|
}
|
|
|
|
const days = Math.floor(hours / 24);
|
|
const remainingHours = hours % 24;
|
|
return remainingHours > 0 ? `${days}d ${remainingHours}h` : `${days}d`;
|
|
}
|
|
|
|
export function formatAgeFromTimestamp(value, now = Date.now()) {
|
|
if (!value) return 'Unavailable';
|
|
const timestamp = new Date(value).getTime();
|
|
if (Number.isNaN(timestamp)) return 'Unavailable';
|
|
return formatAge(now - timestamp);
|
|
}
|
|
|
|
export function formatBytes(value) {
|
|
const numeric = Number(value);
|
|
if (!Number.isFinite(numeric)) return 'Unavailable';
|
|
const units = ['B', 'KiB', 'MiB', 'GiB', 'TiB'];
|
|
let amount = Math.max(0, numeric);
|
|
let unitIndex = 0;
|
|
while (amount >= 1024 && unitIndex < units.length - 1) {
|
|
amount /= 1024;
|
|
unitIndex += 1;
|
|
}
|
|
const digits = amount >= 100 || unitIndex === 0 ? 0 : amount >= 10 ? 1 : 2;
|
|
return `${amount.toFixed(digits)} ${units[unitIndex]}`;
|
|
}
|
|
|
|
export function formatEur(value) {
|
|
if (value == null || value === '') return 'Unavailable';
|
|
const numeric = Number(value);
|
|
if (!Number.isFinite(numeric)) return String(value);
|
|
return new Intl.NumberFormat('en-US', {
|
|
style: 'currency',
|
|
currency: 'EUR',
|
|
maximumFractionDigits: 2,
|
|
}).format(numeric);
|
|
}
|
|
|
|
export function signedClass(value) {
|
|
const numeric = Number(value);
|
|
if (!Number.isFinite(numeric)) return '';
|
|
if (numeric > 0) return 'value-positive';
|
|
if (numeric < 0) return 'value-negative';
|
|
return '';
|
|
}
|
|
|
|
export function truncateMiddle(value, maxLength = 40) {
|
|
const text = String(value || '');
|
|
if (!text || text.length <= maxLength) return text;
|
|
const visible = Math.max(8, maxLength - 1);
|
|
const startLength = Math.ceil(visible / 2);
|
|
const endLength = Math.floor(visible / 2);
|
|
return `${text.slice(0, startLength)}…${text.slice(-endLength)}`;
|
|
}
|
|
|
|
export function stringifyJson(value) {
|
|
return JSON.stringify(value, null, 2);
|
|
}
|