Files
openclaw/packages/normalization-core/src/format.ts
Peter Steinberger e686693732 feat(tooling): adopt noUncheckedIndexedAccess via a strict-ratchet lane (phase 1) (#104577)
* feat(tooling): add noUncheckedIndexedAccess strict-ratchet lane

* fix(packages): make indexed access explicit across ratchet packages

Burns down all 65 noUncheckedIndexedAccess errors in the seven ratchet
packages with behavior-identical restructuring (iteration, charAt/slice,
regex-group guards, validated hextet tuple). net-policy invariant
violations now throw instead of failing open. Adds
@openclaw/normalization-core/expect (expectDefined/first/last) with
subpath export and tests. memory-host-sdk fixes kept but the package
stays out of the lane: it re-exports core src/** so the flag would apply
transitively to all of core.

* fix(lint): keep .oxlintrc.json strict-JSON parseable for extension lint wrappers
2026-07-11 10:26:12 -07:00

45 lines
1.7 KiB
TypeScript

import { expectDefined } from "./expect.js";
type ByteSizeUnit = "byte" | "kilo" | "mega" | "giga" | "tera";
type ByteSizeStyle = "iec" | "legacy-binary";
type ByteSizeFormatOptions = {
style: ByteSizeStyle;
maxUnit: ByteSizeUnit;
separator: "" | " ";
fractionDigits: number | ((value: number, unit: ByteSizeUnit) => number | null);
floorUnits?: readonly ByteSizeUnit[];
};
const BYTE_SIZE_UNITS: readonly ByteSizeUnit[] = ["byte", "kilo", "mega", "giga", "tera"];
const BYTE_SIZE_STYLES = {
iec: { base: 1024, labels: ["B", "KiB", "MiB", "GiB", "TiB"] },
"legacy-binary": { base: 1024, labels: ["B", "KB", "MB", "GB", "TB"] },
} as const satisfies Record<ByteSizeStyle, { base: number; labels: readonly string[] }>;
/** Formats a byte count with caller-explicit scale, labels, precision, and unit cap. */
export function formatByteSize(bytes: number, options: ByteSizeFormatOptions): string {
const { base, labels } = BYTE_SIZE_STYLES[options.style];
const maxUnitIndex = BYTE_SIZE_UNITS.indexOf(options.maxUnit);
let unitIndex = 0;
let value = bytes;
while (value >= base && unitIndex < maxUnitIndex) {
value /= base;
unitIndex += 1;
}
const unit = expectDefined(BYTE_SIZE_UNITS[unitIndex], "byte-size unit");
const label = expectDefined(labels[unitIndex], "byte-size label");
const fractionDigits =
typeof options.fractionDigits === "function"
? options.fractionDigits(value, unit)
: options.fractionDigits;
if (fractionDigits === null) {
return `${value}${options.separator}${label}`;
}
if (options.floorUnits?.includes(unit)) {
value = Math.floor(value * 10 ** fractionDigits) / 10 ** fractionDigits;
}
return `${value.toFixed(fractionDigits)}${options.separator}${label}`;
}