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;
|
type UseAuthProps = { authUrl?: string; apiUrl?: string } | undefined;
|
||||||
export type UserWithToken = User & { token: string };
|
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 = {}) => {
|
export const useAuth = (props: UseAuthProps = {}) => {
|
||||||
const { authUrl = '/api/auth', apiUrl = '/api' } = props;
|
const { authUrl = '/api/auth', apiUrl = '/api' } = props;
|
||||||
const queryClient = useQueryClient();
|
const queryClient = useQueryClient();
|
||||||
@@ -43,7 +53,7 @@ export const useAuth = (props: UseAuthProps = {}) => {
|
|||||||
|
|
||||||
const signin = async ({ email, password }: { email: string; password: string }) => {
|
const signin = async ({ email, password }: { email: string; password: string }) => {
|
||||||
localStorage.removeItem('BEARER_TOKEN');
|
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;
|
const { user, token } = data;
|
||||||
|
|
||||||
@@ -52,9 +62,13 @@ export const useAuth = (props: UseAuthProps = {}) => {
|
|||||||
return;
|
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'] });
|
queryClient.invalidateQueries({ queryKey: ['CURRENT_USER'] });
|
||||||
return data.token;
|
return token;
|
||||||
};
|
};
|
||||||
|
|
||||||
const signout = async () => {
|
const signout = async () => {
|
||||||
@@ -81,7 +95,7 @@ export const useAuth = (props: UseAuthProps = {}) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const changePassword = async (payload: ChangePasswordPayload) => {
|
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) {
|
if (data.token) {
|
||||||
localStorage.setItem('BEARER_TOKEN', data.token);
|
localStorage.setItem('BEARER_TOKEN', data.token);
|
||||||
queryClient.invalidateQueries({ queryKey: ['CURRENT_USER'] });
|
queryClient.invalidateQueries({ queryKey: ['CURRENT_USER'] });
|
||||||
|
|||||||
@@ -68,7 +68,7 @@ export const get = async <T>(uri: string, baseUrl = '') => {
|
|||||||
const res = await fetch(theUrl, { headers });
|
const res = await fetch(theUrl, { headers });
|
||||||
await validateResponse(res);
|
await validateResponse(res);
|
||||||
const data = await res.json();
|
const data = await res.json();
|
||||||
return data as T | any;
|
return data as T;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getBlob = async (uri: string, baseUrl = '') => {
|
export const getBlob = async (uri: string, baseUrl = '') => {
|
||||||
@@ -101,7 +101,7 @@ export const post = async <T>(uri: string, payload?: any, baseUrl = '') => {
|
|||||||
});
|
});
|
||||||
await validateResponse(res);
|
await validateResponse(res);
|
||||||
const data = await res.json();
|
const data = await res.json();
|
||||||
return data as T | any;
|
return data as T;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const put = async <T>(uri: string, payload?: any, baseUrl = '') => {
|
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);
|
await validateResponse(res);
|
||||||
const data = await res.json();
|
const data = await res.json();
|
||||||
return data as T | any;
|
return data as T;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const patch = async <T>(uri: string, payload?: any, baseUrl = '') => {
|
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);
|
await validateResponse(res);
|
||||||
const data = await res.json();
|
const data = await res.json();
|
||||||
return data as T | any;
|
return data as T;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const DELETE = async <T>(uri: string, payload?: any, baseUrl = '') => {
|
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);
|
await validateResponse(res);
|
||||||
const data = await res.json();
|
const data = await res.json();
|
||||||
return data as T | any;
|
return data as T;
|
||||||
};
|
};
|
||||||
|
|
||||||
const validateResponse = async (res: Response) => {
|
const validateResponse = async (res: Response) => {
|
||||||
|
|||||||
Reference in New Issue
Block a user