70 lines
2.2 KiB
TypeScript
70 lines
2.2 KiB
TypeScript
import { AuthState } from "./auth/interfaces";
|
|
import { box } from "boxed_value";
|
|
import { BooleanConfigKey, NumberConfigKey } from "./config_storage/web_app_configs";
|
|
import { BooleanSetting, NumericSetting } from "./session_keys";
|
|
|
|
/** The `Session` namespace is a wrapper for `localStorage`.
|
|
* Use this to avoid direct access of `localStorage` where possible.
|
|
*
|
|
* Problems this namespace aims to solve:
|
|
* - Avoid duplication of localStorage key names.
|
|
* - Avoid duplication of de-serialization logic.
|
|
* - Avoid type errors by explicitly naming keys as (Boolean|Numeric)Setting
|
|
* - Create an upgrade path for the eventual server side storage
|
|
*/
|
|
export namespace Session {
|
|
/** Key that holds the user's JWT */
|
|
const KEY = "session";
|
|
|
|
/** Replace the contents of session storage. */
|
|
export function replaceToken(nextState: AuthState) {
|
|
localStorage.setItem(KEY, JSON.stringify(nextState));
|
|
}
|
|
|
|
/** Fetch the previous session. */
|
|
export function fetchStoredToken(): AuthState | undefined {
|
|
try {
|
|
const v: AuthState = JSON.parse(localStorage.getItem(KEY) || "");
|
|
if (box(v).kind === "object") {
|
|
return v;
|
|
} else {
|
|
throw new Error("Expected object or undefined"); // unreachable?
|
|
}
|
|
} catch (error) {
|
|
return undefined;
|
|
}
|
|
}
|
|
|
|
/** Clear localstorage and sessionstorage. */
|
|
export function clear(): never {
|
|
localStorage.clear();
|
|
sessionStorage.clear();
|
|
window.location.assign(window.location.origin || "/");
|
|
return undefined as never;
|
|
}
|
|
}
|
|
|
|
export const isBooleanSetting =
|
|
// tslint:disable-next-line:no-any
|
|
(x: any): x is BooleanConfigKey => !!BooleanSetting[x as BooleanConfigKey];
|
|
|
|
export function safeBooleanSettting(name: string): BooleanConfigKey {
|
|
if (isBooleanSetting(name)) {
|
|
return name;
|
|
} else {
|
|
throw new Error(`Expected BooleanConfigKey but got '${name}'`);
|
|
}
|
|
}
|
|
|
|
export const isNumericSetting =
|
|
// tslint:disable-next-line:no-any
|
|
(x: any): x is NumberConfigKey => !!NumericSetting[x as NumberConfigKey];
|
|
|
|
export function safeNumericSetting(name: string): NumberConfigKey {
|
|
if (isNumericSetting(name)) {
|
|
return name;
|
|
} else {
|
|
throw new Error(`Expected NumberConfigKey but got '${name}'`);
|
|
}
|
|
}
|