Skip to content

Instantly share code, notes, and snippets.

@xhafan
Created June 7, 2021 06:21
Show Gist options
  • Save xhafan/f23e5e299699b90af60d8b7598acda08 to your computer and use it in GitHub Desktop.
Save xhafan/f23e5e299699b90af60d8b7598acda08 to your computer and use it in GitHub Desktop.
Storage helper with record versioning and expiration support
// initialization: initializeStorage(localStorage);
// usage: storageSetItem("key", "value");
// storageGetItem("key");
// storageRemoveItem("key");
const StorageKeyPrefix = "YourPrefix";
const StorageKeyVersionedPrefix = `${StorageKeyPrefix}_v1_`;
const DefaultStorageItemExpirationInMiliseconds = 14 * 24 * 60 * 60 * 1000; // 14 days
export class StorageItem {
timestamp: number;
value: string;
constructor(timestamp: number, value: string) {
this.timestamp = timestamp;
this.value = value;
}
}
export interface IStorage {
getItem(key): string | null;
setItem(key: string, value: string);
removeItem(key: string);
};
let _storage: IStorage;
let _storageItemExpirationInMiliseconds: number;
let _storageKeyVersionedPrefix: string = StorageKeyVersionedPrefix;
export function getStoragePrefixedKey(key: string): string {
return `${_storageKeyVersionedPrefix}${key}`;
}
export function initializeStorage(
storage: IStorage,
storageItemExpirationInMiliseconds: number = DefaultStorageItemExpirationInMiliseconds
) {
_storage = storage;
_storageItemExpirationInMiliseconds = storageItemExpirationInMiliseconds;
storagePurgeExpiredItems();
}
function getStorage(): IStorage {
if (!_storage) throw new Error("Storage is not initialized. Call initializeStorage() first.");
return _storage;
}
export function storageSetItem(key: string, value: string) {
getStorage().setItem(
getStoragePrefixedKey(key),
JSON.stringify(new StorageItem(Date.now(), value))
);
}
export function storageGetItem(key: string): string | null {
const valueWithExpiration = getStorage().getItem(getStoragePrefixedKey(key));
if (!valueWithExpiration) return null;
const storageItem = JSON.parse(valueWithExpiration) as StorageItem;
return storageItem.value;
}
export function storageRemoveItem(key: string) {
getStorage().removeItem(getStoragePrefixedKey(key));
}
export function storagePurgeExpiredItems() {
const storage = getStorage();
const storageItemKeys = Object.keys(storage);
storageItemKeys.forEach(key => {
if (!key.startsWith(StorageKeyPrefix)) return;
if (!key.startsWith(StorageKeyVersionedPrefix)) {
storage.removeItem(key);
return;
}
const storageItem = JSON.parse(storage.getItem(key)!) as StorageItem;
const expirationDateTime = storageItem.timestamp + _storageItemExpirationInMiliseconds;
if (expirationDateTime < Date.now()) {
storage.removeItem(key);
}
});
}
export function setStorageVersionedPrefix(storageKeyVersionedPrefix: string) {
_storageKeyVersionedPrefix = storageKeyVersionedPrefix;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment