()
| 17 | import type { ILoginInput, ILoginResponse } from "./Auth.types"; |
| 18 | |
| 19 | export function useLogin(): UseMutationResult< |
| 20 | ILoginResponse, |
| 21 | unknown, |
| 22 | ILoginInput |
| 23 | > { |
| 24 | const qc = useQueryClient(); |
| 25 | |
| 26 | return useMutation({ |
| 27 | mutationFn: async (input: ILoginInput): Promise<ILoginResponse> => { |
| 28 | const { data } = await apiClient.POST("/api/v1/auth/login", { |
| 29 | body: input |
| 30 | }); |
| 31 | |
| 32 | if (!data?.data) { |
| 33 | throw new ApiError(0, { message: "Empty login response" }); |
| 34 | } |
| 35 | |
| 36 | const payload = data.data; |
| 37 | |
| 38 | if (isMfaRequiredEnvelope(payload)) { |
| 39 | return { |
| 40 | kind: "mfa-required", |
| 41 | challengeToken: payload.challengeToken |
| 42 | }; |
| 43 | } |
| 44 | |
| 45 | if (isLoginUserEnvelope(payload)) { |
| 46 | return { kind: "session", user: payload.user }; |
| 47 | } |
| 48 | |
| 49 | throw new ApiError(0, { message: "Unrecognised login response shape" }); |
| 50 | }, |
| 51 | onSuccess: async (result: ILoginResponse) => { |
| 52 | /* |
| 53 | * Cookies aren't issued yet on the mfa-required branch; the MFA |
| 54 | * verify mutation establishes the session. |
| 55 | */ |
| 56 | if (result.kind === "mfa-required") { |
| 57 | return; |
| 58 | } |
| 59 | |
| 60 | /* |
| 61 | * Pre-fetch /me before the consumer navigates. Chromium under |
| 62 | * Playwright sometimes lags the Set-Cookie commit behind the |
| 63 | * login response; without this guard the post-redirect |
| 64 | * ProtectedRoute reads useMe, the cookie isn't yet in the |
| 65 | * cookie jar, /me returns {user: null}, and the SPA bounces |
| 66 | * back to /login. `syncMeAfterSessionEstablished` retries |
| 67 | * briefly to ride out the commit window and populates the me |
| 68 | * cache authoritatively so the post-navigation useMe is a |
| 69 | * cache hit, not a refetch. |
| 70 | */ |
| 71 | await syncMeAfterSessionEstablished(qc); |
| 72 | await qc.invalidateQueries({ queryKey: CAPABILITIES_QUERY_KEY }); |
| 73 | } |
| 74 | }); |
| 75 | } |
| 76 |
no test coverage detected