Add storage-estimate core and adapter (M6 Storage Monitor groundwork)

Portable summarizer (clamped fraction, ok/warning/critical level, availability
flag, humanizeBytes) with the browser StorageManager.estimate() feature-detect
isolated to the infrastructure adapter. No UI consumer yet — core-first per the
AI developer protocol; the Storage Monitor panel (spec §02) wires to it next.
This commit is contained in:
2026-06-07 17:14:07 +03:00
parent 548aa199d9
commit f92118712c
3 changed files with 272 additions and 0 deletions
@@ -0,0 +1,39 @@
/**
* Storage estimate adapter (spec §02 → Storage Monitor; docs/architecture/02 §6).
*
* This is the ONLY module that touches the browser's Storage Manager API
* (`navigator.storage.estimate()`). It feature-detects the API, then defers all
* presentation math to the portable core (`src/core/storage-estimate.ts`). When
* the API is unavailable — older browsers, insecure contexts — it returns an
* unavailable summary rather than throwing, so callers get a total function.
*/
import { summarizeStorage, type StorageSummary } from '../../core/storage-estimate';
/** The unavailable summary, returned when the Storage Manager API is absent. */
const UNAVAILABLE: StorageSummary = {
usedBytes: 0,
quotaBytes: 0,
fraction: 0,
level: 'ok',
available: false,
};
/**
* Read the browser's storage estimate and summarize it. Returns an unavailable
* summary when `navigator.storage.estimate` is missing or the call rejects;
* never throws. All math lives in `summarizeStorage`.
*/
export async function readStorageEstimate(): Promise<StorageSummary> {
const storage = typeof navigator !== 'undefined' ? navigator.storage : undefined;
if (!storage || typeof storage.estimate !== 'function') {
return UNAVAILABLE;
}
try {
const { usage, quota } = await storage.estimate();
return summarizeStorage({ usage, quota });
} catch {
return UNAVAILABLE;
}
}