Files
skt-vuetify-templates/src/services/interceptors.ts
T
skytek_xinliang 71683482e1 refactor: ky
2026-05-07 11:17:30 +08:00

86 lines
2.5 KiB
TypeScript

import type { Hooks } from 'ky'
import { isHTTPError } from 'ky'
import { extractErrorMessage, normalizeError } from './error'
import { emitHttpError } from './http-error'
import { emitHttpToast } from './http-toast'
import { emitForceLogout } from './session'
import { tokenService } from './token'
export function createHooks(): Hooks {
return {
beforeRequest: [
({ request }) => {
const token = tokenService.getToken()
const url = request.url
const shouldAttachToken = !url.includes('/Auth/login')
if (token && shouldAttachToken) {
request.headers.set('Authorization', `Bearer ${token}`)
}
},
],
beforeError: [
({ request, options, error }) => {
const normalized = normalizeError(error)
if (normalized.name === 'CanceledRequestError') {
return normalized
}
const requestUrl = request.url
const isLoginRequest = requestUrl.includes('/Auth/login')
const silentToast = Boolean(options.context.silentToast)
const status = isHTTPError(error) ? error.response.status : undefined
switch (status) {
case 401: {
if (requestUrl.includes('/Auth/login')) break
const hasAuthHeader = request.headers.has('Authorization')
if (hasAuthHeader) {
tokenService.clearToken()
const backendMessage = isHTTPError(error) ? extractErrorMessage(error.data) : undefined
emitForceLogout({ message: backendMessage })
}
break
}
case 403: {
emitHttpError({ status, message: normalized.message })
break
}
case 404: {
emitHttpError({ status, message: normalized.message })
break
}
case 500: {
break
}
case 503: {
emitHttpError({ status, message: normalized.message })
break
}
default:
}
const shouldToast =
!silentToast &&
!isLoginRequest &&
status !== 401 &&
status !== 403 &&
status !== 404 &&
status !== 503 &&
(status === 500 || !status || (typeof status === 'number' && status >= 500))
if (shouldToast) {
emitHttpToast({
level: status ? 'error' : 'warning',
message: normalized.message,
})
}
return normalized
},
],
}
}