From 0041fcbd479fee650e2a37a8335de717936302eb Mon Sep 17 00:00:00 2001 From: brunorezio Date: Sat, 25 Jul 2026 23:04:17 +0100 Subject: [PATCH] make useClient actually return its type parameter MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Every verb ended in `return data as T | any`, and `T | any` collapses to `any` — so client.get() handed back `any` and no annotation downstream meant anything. That was the source of most of the implicit-any errors: the callbacks had nothing to infer from. Returning `as T` drops the whole class (19 errors to 9) rather than annotating each parameter. Two calls in useAuth were relying on the looseness and now declare their response shapes. signin also no longer stores `undefined` as the bearer token when the server withholds one; that path returns early. Co-Authored-By: Claude Opus 5 --- src/workspaces/hooks/src/useAuth/useAuth.ts | 22 +++++++++++++++++---- src/workspaces/hooks/src/useClient.ts | 10 +++++----- 2 files changed, 23 insertions(+), 9 deletions(-) diff --git a/src/workspaces/hooks/src/useAuth/useAuth.ts b/src/workspaces/hooks/src/useAuth/useAuth.ts index b8aa8b95..af975267 100644 --- a/src/workspaces/hooks/src/useAuth/useAuth.ts +++ b/src/workspaces/hooks/src/useAuth/useAuth.ts @@ -7,6 +7,16 @@ import { usePasskeys } from './usePasskeys'; type UseAuthProps = { authUrl?: string; apiUrl?: string } | undefined; export type UserWithToken = User & { token: string }; +// POST /auth/signin — `token` is withheld when the account has passkeys, which routes the caller +// through the passkey challenge instead. +type SigninResponse = { + token?: string; + user: User & { passkeys: number }; +}; + +// POST /auth/change-password — a fresh token, since changing the password invalidates the old one. +type TokenResponse = { token?: string }; + export const useAuth = (props: UseAuthProps = {}) => { const { authUrl = '/api/auth', apiUrl = '/api' } = props; const queryClient = useQueryClient(); @@ -43,7 +53,7 @@ export const useAuth = (props: UseAuthProps = {}) => { const signin = async ({ email, password }: { email: string; password: string }) => { localStorage.removeItem('BEARER_TOKEN'); - const data = await authClient.post('/signin', { email, password }); + const data = await authClient.post('/signin', { email, password }); const { user, token } = data; @@ -52,9 +62,13 @@ export const useAuth = (props: UseAuthProps = {}) => { return; } - localStorage.setItem('BEARER_TOKEN', data.token); + // The server only withholds the token for the passkey flow handled above, so this should not + // happen — but storing `undefined` would persist the literal string "undefined" as the token. + if (!token) return; + + localStorage.setItem('BEARER_TOKEN', token); queryClient.invalidateQueries({ queryKey: ['CURRENT_USER'] }); - return data.token; + return token; }; const signout = async () => { @@ -81,7 +95,7 @@ export const useAuth = (props: UseAuthProps = {}) => { }; const changePassword = async (payload: ChangePasswordPayload) => { - const data = await authClient.post('/change-password', payload); + const data = await authClient.post('/change-password', payload); if (data.token) { localStorage.setItem('BEARER_TOKEN', data.token); queryClient.invalidateQueries({ queryKey: ['CURRENT_USER'] }); diff --git a/src/workspaces/hooks/src/useClient.ts b/src/workspaces/hooks/src/useClient.ts index d32ef489..ddd18f8e 100644 --- a/src/workspaces/hooks/src/useClient.ts +++ b/src/workspaces/hooks/src/useClient.ts @@ -68,7 +68,7 @@ export const get = async (uri: string, baseUrl = '') => { const res = await fetch(theUrl, { headers }); await validateResponse(res); const data = await res.json(); - return data as T | any; + return data as T; }; export const getBlob = async (uri: string, baseUrl = '') => { @@ -101,7 +101,7 @@ export const post = async (uri: string, payload?: any, baseUrl = '') => { }); await validateResponse(res); const data = await res.json(); - return data as T | any; + return data as T; }; export const put = async (uri: string, payload?: any, baseUrl = '') => { @@ -120,7 +120,7 @@ export const put = async (uri: string, payload?: any, baseUrl = '') => { }); await validateResponse(res); const data = await res.json(); - return data as T | any; + return data as T; }; export const patch = async (uri: string, payload?: any, baseUrl = '') => { @@ -133,7 +133,7 @@ export const patch = async (uri: string, payload?: any, baseUrl = '') => { }); await validateResponse(res); const data = await res.json(); - return data as T | any; + return data as T; }; export const DELETE = async (uri: string, payload?: any, baseUrl = '') => { @@ -146,7 +146,7 @@ export const DELETE = async (uri: string, payload?: any, baseUrl = '') => { }); await validateResponse(res); const data = await res.json(); - return data as T | any; + return data as T; }; const validateResponse = async (res: Response) => {