feat: enhance API and AuthApi with credentials support and async storage handling

- Added `credentials` option to `ApiOptions` and `BaseModuleApiOptions` for better request handling.
- Updated `AuthApi` to pass `verified` status during token updates.
- Refactored storage handling in `Api` to support async operations using a Proxy.
- Improved `Authenticator` to handle cookie domain configuration and JSON request detection.
- Adjusted `useAuth` to ensure logout and verify methods return promises for better async handling.
- Fixed navigation URL construction in `useNavigate` and updated context menu actions in `_data.root.tsx`.
This commit is contained in:
dswbx
2025-10-15 18:41:04 +02:00
parent f4a7cde487
commit 9070f96571
9 changed files with 85 additions and 56 deletions

View File

@@ -44,18 +44,17 @@ export const ClientProvider = ({
...apiProps,
verbose: isDebug(),
onAuthStateChange: (state) => {
const { token, ...rest } = state;
props.onAuthStateChange?.(state);
if (!authState?.token || state.token !== authState?.token) {
setAuthState(state);
if (!authState?.token || token !== authState?.token) {
setAuthState(rest);
}
},
}),
[JSON.stringify(apiProps)],
);
const [authState, setAuthState] = useState<Partial<AuthState> | undefined>(
apiProps.user ? api.getAuthState() : undefined,
);
const [authState, setAuthState] = useState<Partial<AuthState> | undefined>(api.getAuthState());
return (
<ClientContext.Provider value={{ baseUrl: api.baseUrl, api, authState }}>

View File

@@ -16,8 +16,8 @@ type UseAuth = {
verified: boolean;
login: (data: LoginData) => Promise<AuthResponse>;
register: (data: LoginData) => Promise<AuthResponse>;
logout: () => void;
verify: () => void;
logout: () => Promise<void>;
verify: () => Promise<void>;
setToken: (token: string) => void;
};
@@ -42,12 +42,13 @@ export const useAuth = (options?: { baseUrl?: string }): UseAuth => {
}
async function logout() {
api.updateToken(undefined);
invalidate();
await api.auth.logout();
await invalidate();
}
async function verify() {
await api.verifyAuth();
await invalidate();
}
return {

View File

@@ -95,7 +95,7 @@ export function useNavigate() {
window.location.href = url;
return;
} else if ("target" in options) {
const _url = window.location.origin + basepath + router.base + url;
const _url = window.location.origin + router.base + url;
window.open(_url, options.target);
return;
}

View File

@@ -215,7 +215,9 @@ const EntityContextMenu = ({
href && {
icon: IconExternalLink,
label: "Open in tab",
onClick: () => navigate(href, { target: "_blank" }),
onClick: () => {
navigate(href, { target: "_blank", absolute: true });
},
},
separator,
!$data.system(entity.name).any && {