Files
openchamber/packages/web/server/lib/quota/utils/formatters.js
T
11e5ab93a9 fix(quota): guard remaining usage percent (#1242)
* fix(quota): guard remaining usage percent

* test(quota): cover non-finite usage percents

* fix(ui): clean up virtual scroll frame

---------

Co-authored-by: Isaac Sanchez <isanchez-hawkins@arize.com>
Co-authored-by: Bohdan Triapitsyn <artmore@protonmail.com>
2026-05-13 14:51:46 +03:00

86 lines
2.6 KiB
JavaScript

export const formatResetTime = (timestamp) => {
try {
const resetDate = new Date(timestamp);
if (!Number.isFinite(resetDate.getTime())) {
return null;
}
const now = new Date();
const isToday = resetDate.toDateString() === now.toDateString();
if (isToday) {
return resetDate.toLocaleTimeString(undefined, {
hour: 'numeric',
minute: '2-digit'
});
}
return resetDate.toLocaleString(undefined, {
month: 'short',
day: 'numeric',
weekday: 'short',
hour: 'numeric',
minute: '2-digit'
});
} catch {
return null;
}
};
const hasResetTimestamp = (resetAt) => resetAt !== null && resetAt !== undefined && resetAt !== '';
export const calculateResetAfterSeconds = (resetAt) => {
if (!hasResetTimestamp(resetAt)) return null;
const resetAtTime = new Date(resetAt).getTime();
if (!Number.isFinite(resetAtTime)) return null;
const delta = Math.floor((resetAtTime - Date.now()) / 1000);
return delta < 0 ? 0 : delta;
};
export const toUsageWindow = ({ usedPercent, windowSeconds, resetAt, valueLabel }) => {
const resetAfterSeconds = calculateResetAfterSeconds(resetAt);
const resetFormatted = hasResetTimestamp(resetAt) ? formatResetTime(resetAt) : null;
const hasFiniteUsedPercent = typeof usedPercent === 'number' && Number.isFinite(usedPercent);
return {
usedPercent,
remainingPercent: hasFiniteUsedPercent ? Math.max(0, 100 - usedPercent) : null,
windowSeconds: windowSeconds ?? null,
resetAfterSeconds,
resetAt,
resetAtFormatted: resetFormatted,
resetAfterFormatted: resetFormatted,
...(valueLabel ? { valueLabel } : {})
};
};
export const buildResult = ({ providerId, providerName, ok, configured, usage, error }) => ({
providerId,
providerName,
ok,
configured,
usage: usage ?? null,
...(error ? { error } : {}),
fetchedAt: Date.now()
});
export const durationToLabel = (duration, unit) => {
if (!duration || !unit) return 'limit';
if (unit === 'TIME_UNIT_MINUTE') return `${duration}m`;
if (unit === 'TIME_UNIT_HOUR') return `${duration}h`;
if (unit === 'TIME_UNIT_DAY') return `${duration}d`;
return 'limit';
};
export const durationToSeconds = (duration, unit) => {
if (!duration || !unit) return null;
if (unit === 'TIME_UNIT_MINUTE') return duration * 60;
if (unit === 'TIME_UNIT_HOUR') return duration * 3600;
if (unit === 'TIME_UNIT_DAY') return duration * 86400;
return null;
};
export const formatMoney = (value) => {
if (typeof value !== 'number' || !Number.isFinite(value)) return null;
return value.toFixed(2);
};