Files
textbee/web/lib/httpBrowserClient.ts
isra el dbea68ab30 refactor: modernize nextauth wrapper and provider setup
- extract the provider tree into app/(app)/providers.tsx and create the
  QueryClient once via useState (it was rebuilt on every render, discarding
  the cache); remove the old layout-wrapper
- replace the per-navigation whoAmI session check with a global 401 response
  interceptor in httpBrowserClient that routes expired sessions to /logout
- rename middleware.ts -> proxy.ts (Next 16 convention), clearing the
  deprecation warning; auth guard verified by e2e
- fix .env.example: NEXTAUTH_SECRET (was mislabeled AUTH_SECRET) + NEXTAUTH_URL
- add an e2e assertion for the authenticated login -> dashboard redirect

Build, 19 unit tests, and 3 e2e all green.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-11 01:40:25 +03:00

59 lines
1.5 KiB
TypeScript

import axios from 'axios'
import { getSession } from 'next-auth/react'
const httpBrowserClient = axios.create({
baseURL: process.env.NEXT_PUBLIC_API_BASE_URL || '',
})
// Cache for session data to reduce API calls
let sessionCache: any = null
let cacheTimestamp = 0
const CACHE_DURATION = 2 * 60 * 1000 // 2 minutes
const getCachedSession = async () => {
const now = Date.now()
// Return cached session if it's still valid
if (sessionCache && (now - cacheTimestamp) < CACHE_DURATION) {
return sessionCache
}
// Fetch fresh session and update cache
const session = await getSession()
sessionCache = session
cacheTimestamp = now
return session
}
httpBrowserClient.interceptors.request.use(async (config) => {
const session = await getCachedSession()
if (session?.user?.accessToken) {
config.headers.Authorization = `Bearer ${session.user.accessToken}`
}
return config
})
// Global session-expiry handling: any 401 from the API means the stored token
// is no longer valid, so send the user to logout. This replaces the previous
// per-navigation whoAmI check in the layout wrapper.
httpBrowserClient.interceptors.response.use(
(response) => response,
(error) => {
if (
typeof window !== 'undefined' &&
error?.response?.status === 401
) {
const { pathname } = window.location
if (!pathname.includes('/logout') && !pathname.includes('/login')) {
sessionCache = null
window.location.href = '/logout'
}
}
return Promise.reject(error)
}
)
export default httpBrowserClient