# Дизайн: чистый помощник `formatBytes` — человекочитаемый размер **Дата:** 2026-06-14 ## Цель Дать переиспользуемую чистую функцию, превращающую число байт в короткую человекочитаемую строку (`1536` → `1.5 KB`). Нужна в логах и отчётах размеров файлов/дампов, где сейчас размеры печатаются сырыми байтами и плохо читаются. ## Контракт {#D1} `formatBytes(n, { precision = 1 } = {}) → string`. Вход — неотрицательное число байт. Выход — строка вида `"<число> <единица>"`, единицы по основанию 1024: `B`, `KB`, `MB`, `GB`, `TB`. Дробная часть округляется до `precision` знаков; для единицы `B` дробная часть не печатается (целые байты). Функция детерминирована, без побочных эффектов и без обращения к I/O. ## Алгоритм {#D2} 1. Привести вход к числу; невалидный/отрицательный/`NaN` — см. крайние случаи (D3). 2. Выбрать наибольшую единицу `u`, при которой `n / 1024^i < 1024` (или последняя — `TB`). 3. Значение = `n / 1024^i`; для `i === 0` (`B`) вернуть целое; иначе округлить до `precision` и убрать хвостовые нули. 4. Склеить `"<значение> <единица>"`. ## Крайние случаи {#D3} - `0` → `"0 B"`. - Отрицательное число / `NaN` / не-число → `"0 B"` (деградация к безопасному, без исключения). - Очень большие значения (> 1024 TB) остаются в `TB` (последняя единица не переполняется в новую). - `precision = 0` → без дробной части во всех единицах. ## Конвенция {#D4} ES-модуль `tools/format-bytes.mjs`, единственный именованный экспорт `formatBytes`. Без зависимостей. Покрытие — vitest tools-config. Имя файла и экспорта совпадают по смыслу; чистая функция тестируется в изоляции. ## Критерий готовности {#D5} - Юнит-тесты: базовые переходы единиц (`B`/`KB`/`MB`/`GB`/`TB`), округление по `precision`, целые байты для `B`, безопасная деградация невалидного входа в `"0 B"`. - Полная регрессия tools-only зелёная: `npx vitest run --root app --config vitest.config.tools.mjs`. ```verified-context-json [ {"id": "vc-pricing", "kind": "EXTRACTED", "ref": "tools/cost-pricing.mjs", "anchor": "export const PRICING = Object.freeze("} ] ```