import { createAppAuth, type DefaultAuthUser } from '@nstart/auth' import { createContext, type ReactNode, useContext, useEffect } from 'react' import { setApiAuthToken } from '../api/apiFetch' import { env } from '../config/env' export type AppUser = DefaultAuthUser // Состояние, совместимое с AuthState из @nstart/auth (headless-ядро). Используем // ТОЛЬКО headless-слой пакета: createAppAuth/useAppAuth дают токен, login, logout, // loading и коды ошибок — без единого компонента @nstart/ui (их UI: ProfilePage/ // UserPanel — намеренно не подключаем). interface AppAuthState { user: AppUser | null token: string | null loading: boolean errorCode: 'notAuthenticated' | 'initFailed' | null errorDetails: string | null login: () => void logout: () => void } // Anonymous-режим: фейковый контекст, чтобы useAppAuth() работал везде в коде // без условий. Токен null → apiFetch не добавляет Authorization, поведение как у // исходного сервиса (открывается сразу, без Keycloak). const ANONYMOUS_STATE: AppAuthState = { user: null, token: null, loading: false, errorCode: null, errorDetails: null, login: () => undefined, logout: () => undefined, } const AnonymousAuthContext = createContext(ANONYMOUS_STATE) function AnonymousAuthProvider({ children }: { children: ReactNode }) { return ( {children} ) } function useAnonymousAuth(): AppAuthState { return useContext(AnonymousAuthContext) } const newStartIdAuth = createAppAuth({ url: env.newStartIdUrl, realm: env.newStartIdRealm, clientId: env.newStartIdClientId, loginMode: 'redirect', }) export const { AppAuthProvider, useAppAuth } = env.authMode === 'new-start-id' ? newStartIdAuth : { AppAuthProvider: AnonymousAuthProvider, useAppAuth: useAnonymousAuth } /** * Прокидывает токен из useAppAuth() в сетевой слой (держатель apiFetch). Ничего * не рендерит; монтируется внутри AppAuthProvider. В режиме anonymous token === null, * поэтому заголовок Authorization не выставляется и поведение запросов не меняется. * * @returns Ничего не отображает (null). */ export function AuthTokenBridge(): null { const { token } = useAppAuth() useEffect(() => { setApiAuthToken(token ?? null) }, [token]) return null }