Skip to content

Instantly share code, notes, and snippets.

@dobesv
Created November 29, 2022 23:55
Show Gist options
  • Save dobesv/9022c95d39461eaa05e9f2125d72a203 to your computer and use it in GitHub Desktop.
Save dobesv/9022c95d39461eaa05e9f2125d72a203 to your computer and use it in GitHub Desktop.
import storage, {
AnalyticsStorage,
ANY,
GLOBAL,
} from '@analytics/storage-utils';
export interface ConsentStorage extends AnalyticsStorage {
getConsent(): boolean;
setConsent(newValue: boolean): void;
}
export default function createConsentStorage(): ConsentStorage {
/**
* Storage parameter for setItem calls. getItem and removeItem always use
* `ALL`.
*/
let storageMode: 'global' | 'any' = GLOBAL;
/**
* Track the keys we have see so we know what to migrate/remove in
* case consent status changes.
*/
const keys: Set<string> = new Set();
/**
* Call to set the current persistent consent state. Note that consent is OFF by default.
*
* @param newValue true if the user consents to storing analytics tracking cookies
*/
const setConsent = (newValue: boolean): void => {
const newStorageMode = newValue ? ANY : GLOBAL;
const oldStorageMode = storageMode;
if (oldStorageMode !== newStorageMode) {
storageMode = newStorageMode;
// Move keys to the new storage location
for (const key of keys) {
const removed = storage.removeItem(key);
const oldValue = Object.values(removed)[0];
if (typeof oldValue !== 'undefined') {
storage.setItem(key, oldValue, { storage: newStorageMode });
}
}
}
};
/**
* Return the current consent status.
*/
const getConsent = (): boolean => {
return storageMode === ANY;
};
/**
* Store an item into storage.
*
* If the user has given consent and no explicit storage option is provided, this is stored into
* localStorage, cookies, or session storage based on what's available. If there is no consent
* or none of those storage methods are allowed by the browser it stores it into a global variable.
*
* When storing to localStorage or sessionStorage the value will be serialized
* using JSON.stringify, so only objects compatible with that serialization
* method should be used.
*
* @param key Key to store to
* @param value Value - this will be serialized to JSON
* @param options If provided this can override the default storage mode
*/
const setItem = (
key: string,
value: unknown,
options: { storage: string } | string = { storage: storageMode },
): void => {
keys.add(key);
storage.setItem(key, value, options);
};
/**
* Retrieve a value that was stored using setItem.
*
* @param key Key to look up
* @param options If provided this can override the default storage mode
*/
const getItem = (
key: string,
options: { storage: string } | string = { storage: storageMode },
): unknown => {
return storage.getItem(key, options);
};
/**
* Remove an item from storage.
*
* @param key Key to remove
* @param options If provided this can override the default storage mode
*/
const removeItem = (
key: string,
options: { storage: string } | string = { storage: storageMode },
): {
global?: any;
localStorage?: any;
sessionStorage?: any;
cookie?: any;
} => {
keys.delete(key);
return storage.removeItem(key);
};
return { getConsent, setConsent, setItem, getItem, removeItem };
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment