diff --git a/web/packages/base/kv.ts b/web/packages/base/kv.ts index ba00b96d7b..56e47cf30f 100644 --- a/web/packages/base/kv.ts +++ b/web/packages/base/kv.ts @@ -9,12 +9,16 @@ import log from "./log"; * storage is limited to the main thread). * * The "kv" database consists of one object store, "kv". Keys are strings. - * Values can be strings or number or booleans. + * Values can be arbitrary JSON objects. */ interface KVDBSchema extends DBSchema { kv: { key: string; - value: string | number | boolean; + /** + * Typescript doesn't have a native JSON type, so this needs to be + * unknown + */ + value: unknown; }; } @@ -101,8 +105,16 @@ export const clearKVDB = async () => { /** * Return the string value stored corresponding to {@link key}, or `undefined` * if there is no such entry. + * + * Typescript doesn't have a native JSON type, so the return value is type as an + * `unknown`. For primitive types, you can avoid casting by using the + * {@link getKVS} (string), {@link getKVN} (number) or {@link getKVB} (boolean) + * methods that do an additional runtime check of the type. */ -export const getKV = async (key: string) => _getKV(key, "string"); +export const getKV = async (key: string) => { + const db = await kvDB(); + return db.get("kv", key); +}; export const _getKV = async ( key: string, @@ -113,11 +125,14 @@ export const _getKV = async ( if (v === undefined) return undefined; if (typeof v != type) throw new Error( - `Expected the value corresponding to key ${key} to be a ${type}, but instead got ${v}`, + `Expected the value corresponding to key ${key} to be a ${type}, but instead got ${String(v)}`, ); return v as T; }; +/** String variant of {@link getKV}. */ +export const getKVS = async (key: string) => _getKV(key, "string"); + /** Numeric variant of {@link getKV}. */ export const getKVN = async (key: string) => _getKV(key, "number"); @@ -127,8 +142,11 @@ export const getKVB = async (key: string) => _getKV(key, "boolean"); /** * Save the given {@link value} corresponding to {@link key}, overwriting any * existing value. + * + * @param value Any arbitrary JSON object. Typescript doesn't have a native JSON + * type, so this is typed as a unknown */ -export const setKV = async (key: string, value: string | number | boolean) => { +export const setKV = async (key: string, value: unknown) => { const db = await kvDB(); await db.put("kv", value, key); }; diff --git a/web/packages/base/local-user.ts b/web/packages/base/local-user.ts index d38ed5a69c..5a3eeafaac 100644 --- a/web/packages/base/local-user.ts +++ b/web/packages/base/local-user.ts @@ -2,7 +2,7 @@ import { ensure } from "@/utils/ensure"; import { z } from "zod"; -import { getKV } from "./kv"; +import { getKVS } from "./kv"; // TODO: During login the only field present is email. Which makes this // optionality indicated by these types incorrect. @@ -57,4 +57,4 @@ export const ensureLocalUser = (): LocalUser => { * The underlying data is stored in IndexedDB, and can be accessed from web * workers. */ -export const ensureAuthToken = async () => ensure(await getKV("token")); +export const ensureAuthToken = async () => ensure(await getKVS("token")); diff --git a/web/packages/base/origins.ts b/web/packages/base/origins.ts index d1474014a3..f904bebe4d 100644 --- a/web/packages/base/origins.ts +++ b/web/packages/base/origins.ts @@ -1,4 +1,4 @@ -import { getKV } from "@/base/kv"; +import { getKVS } from "@/base/kv"; /** * Return the origin (scheme, host, port triple) that should be used for making @@ -35,7 +35,7 @@ export const apiURL = async (path: string) => (await apiOrigin()) + path; * Otherwise return undefined. */ export const customAPIOrigin = async () => - (await getKV("apiOrigin")) ?? + (await getKVS("apiOrigin")) ?? process.env.NEXT_PUBLIC_ENTE_ENDPOINT ?? undefined; diff --git a/web/packages/new/photos/components/DevSettings.tsx b/web/packages/new/photos/components/DevSettings.tsx index 5a95933216..385acdc585 100644 --- a/web/packages/new/photos/components/DevSettings.tsx +++ b/web/packages/new/photos/components/DevSettings.tsx @@ -1,6 +1,6 @@ import { useIsMobileWidth } from "@/base/hooks"; import { ensureOk } from "@/base/http"; -import { getKV, removeKV, setKV } from "@/base/kv"; +import { getKVS, removeKV, setKV } from "@/base/kv"; import log from "@/base/log"; import InfoOutlinedIcon from "@mui/icons-material/InfoOutlined"; import { @@ -69,7 +69,8 @@ const Contents: React.FC = (props) => { >(); useEffect( - () => void getKV("apiOrigin").then((o) => setInitialAPIOrigin(o ?? "")), + () => + void getKVS("apiOrigin").then((o) => setInitialAPIOrigin(o ?? "")), [], ); diff --git a/web/packages/new/photos/services/user-entity/remote.ts b/web/packages/new/photos/services/user-entity/remote.ts index 17c2123741..c32e253af4 100644 --- a/web/packages/new/photos/services/user-entity/remote.ts +++ b/web/packages/new/photos/services/user-entity/remote.ts @@ -44,7 +44,7 @@ const defaultDiffLimit = 500; */ export interface UserEntityChange { /** - * A UUID or nanoid of the entity. + * The UUID or nanoid of the entity. */ id: string; /** diff --git a/web/packages/shared/storage/localStorage/index.ts b/web/packages/shared/storage/localStorage/index.ts index a90c1d838b..2ba7e17f28 100644 --- a/web/packages/shared/storage/localStorage/index.ts +++ b/web/packages/shared/storage/localStorage/index.ts @@ -1,4 +1,4 @@ -import { getKV, removeKV, setKV } from "@/base/kv"; +import { getKVS, removeKV, setKV } from "@/base/kv"; import log from "@/base/log"; export enum LS_KEYS { @@ -78,7 +78,7 @@ export const migrateKVToken = async (user: unknown) => { typeof oldLSUser == "object" && "token" in oldLSUser && typeof oldLSUser.token == "string" && - !(await getKV("token")); + !(await getKVS("token")); user && typeof user == "object" &&