import { create } from "zustand"; import { userServiceClient } from "@/grpcweb"; import { User } from "@/types/proto/api/v2/user_service"; interface UserV1Store { userMapByUsername: Record; getOrFetchUserByUsername: (username: string) => Promise; getUserByUsername: (username: string) => User; updateUser: (user: Partial, updateMask: string[]) => Promise; } // Request cache is used to prevent multiple requests. const requestCache = new Map>(); const useUserV1Store = create()((set, get) => ({ userMapByUsername: {}, getOrFetchUserByUsername: async (username: string) => { const userMap = get().userMapByUsername; if (userMap[username]) { return userMap[username] as User; } if (requestCache.has(username)) { return await requestCache.get(username); } const promisedUser = userServiceClient .getUser({ username: username, }) .then(({ user }) => user); requestCache.set(username, promisedUser); const user = await promisedUser; if (!user) { throw new Error("User not found"); } requestCache.delete(username); userMap[username] = user; set(userMap); return user; }, getUserByUsername: (username: string) => { const userMap = get().userMapByUsername; return userMap[username]; }, updateUser: async (user: Partial, updateMask: string[]) => { const { user: updatedUser } = await userServiceClient.updateUser({ user: user, updateMask: updateMask, }); if (!updatedUser) { throw new Error("User not found"); } const userMap = get().userMapByUsername; userMap[updatedUser.username] = updatedUser; set(userMap); return updatedUser; }, })); export default useUserV1Store;