The auth store loads tokens from localStorage synchronously at import time, but configureAuth() was deferred to a useEffect — so the first API requests fired before the token getter was wired, causing 401s on hard refresh. Now getAccessToken reads from the store by default. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
37 lines
1.0 KiB
TypeScript
37 lines
1.0 KiB
TypeScript
import createClient, { type Middleware } from 'openapi-fetch';
|
|
import type { paths } from './schema';
|
|
import { config } from '../config';
|
|
import { useAuthStore } from '../auth/auth-store';
|
|
|
|
let getAccessToken: () => string | null = () =>
|
|
useAuthStore.getState().accessToken;
|
|
let onUnauthorized: () => void = () => {};
|
|
|
|
export function configureAuth(opts: {
|
|
getAccessToken?: () => string | null;
|
|
onUnauthorized: () => void;
|
|
}) {
|
|
if (opts.getAccessToken) getAccessToken = opts.getAccessToken;
|
|
onUnauthorized = opts.onUnauthorized;
|
|
}
|
|
|
|
const authMiddleware: Middleware = {
|
|
async onRequest({ request }) {
|
|
const token = getAccessToken();
|
|
if (token) {
|
|
request.headers.set('Authorization', `Bearer ${token}`);
|
|
}
|
|
request.headers.set('X-Cameleer-Protocol-Version', '1');
|
|
return request;
|
|
},
|
|
async onResponse({ response }) {
|
|
if (response.status === 401 || response.status === 403) {
|
|
onUnauthorized();
|
|
}
|
|
return response;
|
|
},
|
|
};
|
|
|
|
export const api = createClient<paths>({ baseUrl: config.apiBaseUrl });
|
|
api.use(authMiddleware);
|