aboutsummaryrefslogtreecommitdiff
path: root/packages/web-util/src
diff options
context:
space:
mode:
authorSebastian <sebasjm@gmail.com>2023-05-26 16:51:47 -0300
committerSebastian <sebasjm@gmail.com>2023-05-26 16:51:47 -0300
commitbe27647ff73d1529372a80c3e145f3ee4f229a17 (patch)
treea8fd227dc5e8e4d871fde98fff0a9e49836a2ba6 /packages/web-util/src
parent62cec679833db48465d67194e39b29db985aa430 (diff)
downloadwallet-core-be27647ff73d1529372a80c3e145f3ee4f229a17.tar.xz
use buildKeyStorage to prevent different type for same key
Diffstat (limited to 'packages/web-util/src')
-rw-r--r--packages/web-util/src/hooks/index.ts2
-rw-r--r--packages/web-util/src/hooks/useLang.ts12
-rw-r--r--packages/web-util/src/hooks/useLocalStorage.ts70
-rw-r--r--packages/web-util/src/hooks/useMemoryStorage.ts60
4 files changed, 77 insertions, 67 deletions
diff --git a/packages/web-util/src/hooks/index.ts b/packages/web-util/src/hooks/index.ts
index ae8872497..a3a2053e6 100644
--- a/packages/web-util/src/hooks/index.ts
+++ b/packages/web-util/src/hooks/index.ts
@@ -1,5 +1,5 @@
export { useLang } from "./useLang.js";
-export { useLocalStorage } from "./useLocalStorage.js";
+export { useLocalStorage, buildStorageKey } from "./useLocalStorage.js";
export { useMemoryStorage } from "./useMemoryStorage.js";
export {
useNotifications,
diff --git a/packages/web-util/src/hooks/useLang.ts b/packages/web-util/src/hooks/useLang.ts
index d64cf6e1a..448cd8aba 100644
--- a/packages/web-util/src/hooks/useLang.ts
+++ b/packages/web-util/src/hooks/useLang.ts
@@ -14,7 +14,11 @@
GNU Anastasis; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
*/
-import { LocalStorageState, useLocalStorage } from "./useLocalStorage.js";
+import {
+ StorageState,
+ buildStorageKey,
+ useLocalStorage,
+} from "./useLocalStorage.js";
function getBrowserLang(): string | undefined {
if (typeof window === "undefined") return undefined;
@@ -23,7 +27,9 @@ function getBrowserLang(): string | undefined {
return undefined;
}
-export function useLang(initial?: string): Required<LocalStorageState> {
+const langPreferenceKey = buildStorageKey("lang-preference");
+
+export function useLang(initial?: string): Required<StorageState> {
const defaultValue = (getBrowserLang() || initial || "en").substring(0, 2);
- return useLocalStorage("lang-preference", { defaultValue: defaultValue });
+ return useLocalStorage(langPreferenceKey, defaultValue);
}
diff --git a/packages/web-util/src/hooks/useLocalStorage.ts b/packages/web-util/src/hooks/useLocalStorage.ts
index 55efd01cb..45b7abd3c 100644
--- a/packages/web-util/src/hooks/useLocalStorage.ts
+++ b/packages/web-util/src/hooks/useLocalStorage.ts
@@ -19,7 +19,7 @@
* @author Sebastian Javier Marchano (sebasjm)
*/
-import { Codec } from "@gnu-taler/taler-util";
+import { Codec, codecForString } from "@gnu-taler/taler-util";
import { useEffect, useState } from "preact/hooks";
import {
ObservableMap,
@@ -28,7 +28,26 @@ import {
memoryMap,
} from "../utils/observable.js";
-export interface LocalStorageState<Type = string> {
+declare const opaque_StorageKey: unique symbol;
+
+export type StorageKey<Key> = {
+ id: string;
+ [opaque_StorageKey]: true;
+ codec: Codec<Key>;
+};
+
+export function buildStorageKey<Key = string>(
+ name: string,
+ codec?: Codec<Key>,
+): StorageKey<Key> {
+ return {
+ id: name,
+ codec: codec ?? (codecForString() as Codec<Key>),
+ [opaque_StorageKey]: true,
+ };
+}
+
+export interface StorageState<Type = string> {
value?: Type;
update: (s: Type) => void;
reset: () => void;
@@ -50,59 +69,48 @@ const storage: ObservableMap<string, string> = (function buildStorage() {
//with initial value
export function useLocalStorage<Type = string>(
- key: string,
- options?: {
- defaultValue: Type;
- codec?: Codec<Type>;
- },
-): Required<LocalStorageState<Type>>;
+ key: StorageKey<Type>,
+ defaultValue: Type,
+): Required<StorageState<Type>>;
//without initial value
export function useLocalStorage<Type = string>(
- key: string,
- options?: {
- codec?: Codec<Type>;
- },
-): LocalStorageState<Type>;
+ key: StorageKey<Type>,
+): StorageState<Type>;
// impl
export function useLocalStorage<Type = string>(
- key: string,
- options?: {
- defaultValue?: Type;
- codec?: Codec<Type>;
- },
-): LocalStorageState<Type> {
+ key: StorageKey<Type>,
+ defaultValue?: Type,
+): StorageState<Type> {
function convert(updated: string | undefined): Type | undefined {
- if (updated === undefined) return options?.defaultValue; //optional
+ if (updated === undefined) return defaultValue; //optional
try {
- return !options?.codec
- ? (updated as Type)
- : options.codec.decode(JSON.parse(updated));
+ return key.codec.decode(JSON.parse(updated));
} catch (e) {
//decode error
- return options?.defaultValue;
+ return defaultValue;
}
}
const [storedValue, setStoredValue] = useState<Type | undefined>(
(): Type | undefined => {
- const prev = storage.get(key);
+ const prev = storage.get(key.id);
return convert(prev);
},
);
useEffect(() => {
- return storage.onUpdate(key, () => {
- const newValue = storage.get(key);
+ return storage.onUpdate(key.id, () => {
+ const newValue = storage.get(key.id);
setStoredValue(convert(newValue));
});
}, []);
const setValue = (value?: Type): void => {
if (value === undefined) {
- storage.delete(key);
+ storage.delete(key.id);
} else {
storage.set(
- key,
- options?.codec ? JSON.stringify(value) : (value as string),
+ key.id,
+ key.codec ? JSON.stringify(value) : (value as string),
);
}
};
@@ -111,7 +119,7 @@ export function useLocalStorage<Type = string>(
value: storedValue,
update: setValue,
reset: () => {
- setValue(options?.defaultValue);
+ setValue(defaultValue);
},
};
}
diff --git a/packages/web-util/src/hooks/useMemoryStorage.ts b/packages/web-util/src/hooks/useMemoryStorage.ts
index 7160b035e..d8be24c1e 100644
--- a/packages/web-util/src/hooks/useMemoryStorage.ts
+++ b/packages/web-util/src/hooks/useMemoryStorage.ts
@@ -20,48 +20,44 @@
*/
import { useEffect, useState } from "preact/hooks";
-import {
- ObservableMap,
- browserStorageMap,
- localStorageMap,
- memoryMap,
-} from "../utils/observable.js";
+import { ObservableMap, memoryMap } from "../utils/observable.js";
+import { StorageKey, StorageState } from "./useLocalStorage.js";
-export interface LocalStorageState {
- value?: string;
- update: (s: string) => void;
- reset: () => void;
-}
-
-const storage: ObservableMap<string, string> = memoryMap<string>();
+const storage: ObservableMap<string, any> = memoryMap<any>();
-export function useMemoryStorage(
- key: string,
- initialValue: string,
-): Required<LocalStorageState>;
-export function useMemoryStorage(key: string): LocalStorageState;
-export function useMemoryStorage(
- key: string,
- initialValue?: string,
-): LocalStorageState {
- const [storedValue, setStoredValue] = useState<string | undefined>(
- (): string | undefined => {
- return storage.get(key) ?? initialValue;
+//with initial value
+export function useMemoryStorage<Type = string>(
+ key: StorageKey<Type>,
+ defaultValue: Type,
+): Required<StorageState<Type>>;
+//with initial value
+export function useMemoryStorage<Type = string>(
+ key: StorageKey<Type>,
+): StorageState<Type>;
+// impl
+export function useMemoryStorage<Type = string>(
+ key: StorageKey<Type>,
+ defaultValue?: Type,
+): StorageState<Type> {
+ const [storedValue, setStoredValue] = useState<Type | undefined>(
+ (): Type | undefined => {
+ const prev = storage.get(key.id);
+ return prev;
},
);
useEffect(() => {
- return storage.onUpdate(key, () => {
- const newValue = storage.get(key);
- setStoredValue(newValue ?? initialValue);
+ return storage.onUpdate(key.id, () => {
+ const newValue = storage.get(key.id);
+ setStoredValue(newValue);
});
}, []);
- const setValue = (value?: string): void => {
+ const setValue = (value?: Type): void => {
if (value === undefined) {
- storage.delete(key);
+ storage.delete(key.id);
} else {
- storage.set(key, value);
+ storage.set(key.id, value);
}
};
@@ -69,7 +65,7 @@ export function useMemoryStorage(
value: storedValue,
update: setValue,
reset: () => {
- setValue(initialValue);
+ setValue(defaultValue);
},
};
}