// TODO: This file belongs to the accounts package import { ensure } from "@/utils/ensure"; import { z } from "zod"; import { getKV } from "./kv"; // TODO: During login the only field present is email. Which makes this // optionality indicated by these types incorrect. const LocalUser = z.object({ /** The user's ID. */ id: z.number(), /** The user's email. */ email: z.string(), /** * The user's (plaintext) auth token. * * It is used for making API calls on their behalf, by passing this token as * the value of the X-Auth-Token header in the HTTP request. */ token: z.string(), }); /** Locally available data for the logged in user */ export type LocalUser = z.infer; /** * Return the logged-in user, if someone is indeed logged in. Otherwise return * `undefined`. * * The user's data is stored in the browser's localStorage. */ export const localUser = (): LocalUser | undefined => { // TODO(MR): duplicate of LS_KEYS.USER const s = localStorage.getItem("user"); if (!s) return undefined; return LocalUser.parse(JSON.parse(s)); }; /** * A wrapper over {@link localUser} with that throws if no one is logged in. */ export const ensureLocalUser = (): LocalUser => { const user = localUser(); if (!user) throw new Error("Not logged in"); return user; }; /** * Return the user's auth token, or throw an error. * * The user's auth token is stored in KV DB after they have successfully logged * in. This function returns that saved auth token. * * If no such token is found (which should only happen if the user is not logged * in), then it throws an error. * * The underlying data is stored in IndexedDB, and can be accessed from web * workers. */ export const ensureAuthToken = async () => ensure(await getKV("token"));