@adrienlcp/safe-storage
localStorage that never throws: every read, write and removal returns a Result, and typed reads check what they find
Fonctionne avec
- TypeScript
Installation
pnpm add @adrienlcp/safe-storageExports
Groupés par la section de la documentation qui les explique. Une ligne mène à sa section.
Reading3 exports
readRecognizedTextThe text stored underkey, narrowed byisRecognized— a locale, a theme, any closed set of strings.FonctionreadStoredJsonThe JSON stored underkey, parsed and narrowed byisValue.FonctionreadStoredTextThe text stored underkey, ornullwhen nothing is: an absence, never a failure.Fonction
Writing and removing3 exports
Documentés dans le code seulement5 exports
StorageUnavailablelocalStoragethrew on access: a Safari private window, storage blocked by the user or a policy, or nolocalStorageat all, as on a server.TypeStoredValueUnrecognizedSomething is stored under the key, but not a value the caller recognizes.TypeStorageQuotaExceededThe browser refused the write because the origin's storage is full.TypeStorageReadErrorTypeStorageWriteErrorType
Documentation
Le README et les documents à côté, tels qu’écrits dans le dépôt.
PrésentationREADME.md
localStorage that never throws. Every read, write and removal returns a
Result, and a typed read checks what it finds instead of
trusting it.
localStorage throws on plain access in a Safari private window, when the
user blocks site data, when the quota is full, and on a server, where it does
not exist. An app that calls it bare turns any of those into a blank page.
pnpm add @adrienlcp/safe-storageReadingREADME.md
import { readRecognizedText, readStoredJson, readStoredText } from '@adrienlcp/safe-storage'
readStoredText('app:volume')
// Result<string | null, 'unavailable'>
readRecognizedText({ isRecognized: isLocale, key: 'app:locale' })
// Result<Locale | null, 'unavailable' | 'unrecognized'>
readStoredJson({ isValue: isTrainingLog, key: 'app:log' })
// Result<TrainingLog | null, 'unavailable' | 'unrecognized'>- A
nullsuccess is nothing stored yet, never a failure. 'unavailable'—localStoragethrew, or there is none.'unrecognized'— something is stored, but the guard refuses it: a value an older version wrote, text that is not JSON, JSON of another shape.
The guard is a plain type predicate, so no schema library is required. One plugs in through its own:
const isTrainingLog = (value: unknown): value is TrainingLog =>
trainingLogSchema.safeParse(value).successWriting and removingREADME.md
import { removeStored, writeStoredJson, writeStoredText } from '@adrienlcp/safe-storage'
writeStoredText({ key: 'app:locale', text: 'fr' }) // Result<void, 'unavailable' | 'quota'>
writeStoredJson({ key: 'app:log', value: log }) // Result<void, 'unavailable' | 'quota'>
removeStored('app:locale') // Result<void, 'unavailable'>'quota' is a full storage. A value JSON.stringify cannot write, like a
cycle, still throws: that is a bug in the caller, not a refusal.
What to do with a failureREADME.md
This package reports; it never decides. What the user gets instead is the app's call, made where the storage is read:
const readTrainingLogOrEmpty = (): TrainingLog => {
const stored = readStoredJson({ isValue: isTrainingLog, key: LOG_KEY })
return stored.status === 'success' ? (stored.data ?? EMPTY_LOG) : EMPTY_LOG
}