Versioned local storage
Problem to be solved:
When working with localStorage
you can run in to some issues
- Does the user already have some data in the
localStorage
? - If the user has data in
localStorage
, is it valid or is it outdated
The goal of the package is to create a wrapper around localStorage
that ensures a valid state, matching the current app version.
Installation:
npm i versioned-local-storage
The project is maintained on Gitlab
Api:
Creating an instance
Creating a new storage instance:
// type is `VersionedLocalStorage<null>`
const storage = getVersionedLocalStorage('storageKey').build();
Every storage instance starts with version number 0
and type null
.
To add a value and type you need to add a new version:
// type is `VersionedLocalStorage<string>`
const storage = getVersionedLocalStorage('storageKey')
.addVersion((oldValue: null) => "some string value")
.build();
It is important never to remove versions that have already been in production. If you'd want to change wrap the string in an object you'd have to add a new version:
// type is `VersionedLocalStorage<{ stringValue: string }>`
const storage = getVersionedLocalStorage('storageKey')
.addVersion(() => "some string value")
.addVersion(oldString => ({ stringValue: oldString }))
.build();
Say you'd want to make stringValue
nullable, typescript won't be able to infer the type by the return value.
You'll need to specify the type explicitly:
// type is `VersionedLocalStorage<{ stringValue?: string }>`
const storage = getVersionedLocalStorage('storageKey')
.addVersion(() => "some string value")
.addVersion(oldString => ({ stringValue: oldString }))
.addVersion<{ stringValue?: string }>(value => value)
.build();
Note that in this case, the value doesn't actually have to change
Reading and updating the values
const storage = getVersionedLocalStorage('storageKey')
.addVersion(() => "some string value")
.addVersion(oldString => ({ stringValue: oldString }))
.addVersion<{ stringValue?: string }>()
.build();
console.log(storage.value);
storage.value = {};
storage.value = { stringValue: 'Different string' };
Setting the .value
attribute updates the localStorage
.
But watch out, you should treat the value as immutable, if you update a property in the value it won't update the localStorage
.
// wrong:
storage.value.stringValue = 'Different string';
// Right:
storage.value = { stringValue: 'Different string' };
Another pitfall is setting a value that has a cyclic reference.
Under the hood, assigning to storage.value
stringifies the value and stores it in localStorage
.
Because objects with a cyclic reference can't be stringify'ed, you also can't assign such an object to storage.value
.
Deprecating a storage key
When you don't need a value anymore you can call .deprecate()
instead of .build()
const storage = getVersionedLocalStorage('storageKey')
.addVersion(() => "some string value")
.addVersion(oldString => ({ stringValue: oldString }))
.addVersion<{ stringValue?: string }>()
.deprecate();