make useClient actually return its type parameter
Every verb ended in `return data as T | any`, and `T | any` collapses to `any` — so client.get<Foo>() 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 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
1fa3a659bc
commit
0041fcbd47
@@ -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<SigninResponse>('/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<TokenResponse>('/change-password', payload);
|
||||
if (data.token) {
|
||||
localStorage.setItem('BEARER_TOKEN', data.token);
|
||||
queryClient.invalidateQueries({ queryKey: ['CURRENT_USER'] });
|
||||
|
||||
@@ -68,7 +68,7 @@ export const get = async <T>(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 <T>(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 <T>(uri: string, payload?: any, baseUrl = '') => {
|
||||
@@ -120,7 +120,7 @@ export const put = async <T>(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 <T>(uri: string, payload?: any, baseUrl = '') => {
|
||||
@@ -133,7 +133,7 @@ export const patch = async <T>(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 <T>(uri: string, payload?: any, baseUrl = '') => {
|
||||
@@ -146,7 +146,7 @@ export const DELETE = async <T>(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) => {
|
||||
|
||||
Reference in New Issue
Block a user