@tdb/util
Version:
Shared helpers and utilities.
120 lines (108 loc) • 2.69 kB
text/typescript
import { R } from '../../libs';
import {
ILocalStorageOptions,
ILocalStorageValue,
StorageValueType,
LocalStorageProp,
} from './types';
import { init as initStore } from './store.web';
import { subject$ } from './events.rx';
const store = initStore();
function asTypeName(value: any): StorageValueType {
if (value === null) {
return 'null';
}
if (R.is(Boolean, value)) {
return 'bool';
}
if (R.is(String, value)) {
return 'string';
}
if (R.is(Number, value)) {
return 'number';
}
if (R.is(Boolean, value)) {
return 'bool';
}
if (R.is(Date, value)) {
return 'date';
}
return 'object';
}
function toValue(key: string, json?: string | null): any {
try {
return parse(json);
} catch (error) {
throw new Error(
`Failed to read '${key}' from storage. The value '${json}' cannot be parsed.`,
);
}
}
export function parse(json?: string | null) {
if (!json) {
return json;
}
// Convert the JSON string to an object.
const item = JSON.parse(json) as ILocalStorageValue;
// Perform type conversions.
switch (item.type) {
case 'null':
case 'bool':
case 'string':
return item.value;
case 'number':
return parseFloat(item.value);
case 'date':
return new Date(item.value);
case 'object':
return item.value;
default: // Ignore.
}
}
/**
* Asynchronous read/write interface to the store.
*
* READ: Pass nothing (undefined) to read the value for the `key` parameter.
* WRITE: Pass a `value` to write.
* CLEAR: Pass null to `value` to clear.
*/
export function prop<T>(
key: string,
defaultOptions: ILocalStorageOptions = {},
): LocalStorageProp<T> {
async function func<T>(value?: T | null, options: ILocalStorageOptions = {}) {
const args = { ...defaultOptions, ...options };
let result: any = value;
const fireEvent = () => {
subject$.next({
key,
value,
type: asTypeName(value),
});
};
if (value === null) {
// CLEAR.
await store.removeItem(key);
fireEvent();
} else if (value !== undefined) {
// WRITE.
const storageValue: ILocalStorageValue = {
value,
type: asTypeName(value),
};
await store.setItem(key, JSON.stringify(storageValue));
fireEvent();
} else {
// READ.
const json = await store.getItem(key);
result = json ? toValue(key, json) : undefined;
}
// Finish up.
return result === undefined ? args.default : (result as T);
}
// Finish up.
const result = func as LocalStorageProp<T>;
result.key = key;
result.isProp = true;
return result;
}