fix(auth): stabilize header session state and retry team token errors

This commit is contained in:
Ruslan Bakiev
2026-04-21 13:50:11 +07:00
parent 7b4eaeeb92
commit e1e6993f35
4 changed files with 78 additions and 28 deletions

View File

@@ -27,6 +27,7 @@ const CLIENT_MAP: Record<string, string> = {
export const useGraphQL = () => {
const auth = useAuth()
const { activeLogtoOrgId } = useActiveTeam()
const { refreshTokens } = useLogtoTokens()
const getClientId = (endpoint: Endpoint, api: Api): string => {
return CLIENT_MAP[`${endpoint}:${api}`] || 'default'
@@ -77,20 +78,37 @@ export const useGraphQL = () => {
): Promise<TResult> => {
const clientId = getClientId(endpoint, api)
const { client } = useApolloClient(clientId)
const context = await getAuthContext(endpoint, api)
const executeOnce = async () => {
const context = await getAuthContext(endpoint, api)
const result = await client.query({
query: document,
variables,
context,
fetchPolicy: 'network-only'
})
const result = await client.query({
query: document,
variables,
context,
fetchPolicy: 'network-only'
})
if (result.errors?.length) {
throw new Error(result.errors[0]?.message || 'GraphQL error')
}
if (result.errors?.length) {
throw new Error(result.errors[0]?.message || 'GraphQL error')
return result.data as TResult
}
return result.data as TResult
try {
return await executeOnce()
} catch (error) {
const message = error instanceof Error ? error.message : String(error)
const isAuthContextFailure = message.includes('Invalid Compact JWS')
|| message.includes('Context creation failed')
|| message.includes('Received status code 500')
if (endpoint === 'team' && isAuthContextFailure) {
await refreshTokens()
return await executeOnce()
}
throw error
}
}
const mutate = async <TResult, TVariables extends Record<string, unknown>>(
@@ -101,19 +119,36 @@ export const useGraphQL = () => {
): Promise<TResult> => {
const clientId = getClientId(endpoint, api)
const { client } = useApolloClient(clientId)
const context = await getAuthContext(endpoint, api)
const mutateOnce = async () => {
const context = await getAuthContext(endpoint, api)
const result = await client.mutate({
mutation: document,
variables,
context
})
const result = await client.mutate({
mutation: document,
variables,
context
})
if (result.errors?.length) {
throw new Error(result.errors[0]?.message || 'GraphQL error')
}
if (result.errors?.length) {
throw new Error(result.errors[0]?.message || 'GraphQL error')
return result.data as TResult
}
return result.data as TResult
try {
return await mutateOnce()
} catch (error) {
const message = error instanceof Error ? error.message : String(error)
const isAuthContextFailure = message.includes('Invalid Compact JWS')
|| message.includes('Context creation failed')
|| message.includes('Received status code 500')
if (endpoint === 'team' && isAuthContextFailure) {
await refreshTokens()
return await mutateOnce()
}
throw error
}
}
return { execute, mutate }