Files
portal/docs/superpowers/specs/2026-06-14-format-bytes-helper-design.md
T

41 lines
3.1 KiB
Markdown

# Дизайн: чистый помощник `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("}
]
```