| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889 | 
							- 'use client'
 - import { useCallback, useEffect, useRef } from 'react'
 - import { jwtDecode } from 'jwt-decode'
 - import dayjs from 'dayjs'
 - import utc from 'dayjs/plugin/utc'
 - import { useRouter } from 'next/navigation'
 - import type { CommonResponse } from '@/models/common'
 - import { fetchNewToken } from '@/service/common'
 - import { fetchWithRetry } from '@/utils'
 - 
 - dayjs.extend(utc)
 - 
 - const useRefreshToken = () => {
 -   const router = useRouter()
 -   const timer = useRef<NodeJS.Timeout>()
 -   const advanceTime = useRef<number>(5 * 60 * 1000)
 - 
 -   const getExpireTime = useCallback((token: string) => {
 -     if (!token)
 -       return 0
 -     const decoded = jwtDecode(token)
 -     return (decoded.exp || 0) * 1000
 -   }, [])
 - 
 -   const getCurrentTimeStamp = useCallback(() => {
 -     return dayjs.utc().valueOf()
 -   }, [])
 - 
 -   const handleError = useCallback(() => {
 -     localStorage?.removeItem('is_refreshing')
 -     localStorage?.removeItem('console_token')
 -     localStorage?.removeItem('refresh_token')
 -     router.replace('/signin')
 -   }, [])
 - 
 -   const getNewAccessToken = useCallback(async () => {
 -     const currentAccessToken = localStorage?.getItem('console_token')
 -     const currentRefreshToken = localStorage?.getItem('refresh_token')
 -     if (!currentAccessToken || !currentRefreshToken) {
 -       handleError()
 -       return new Error('No access token or refresh token found')
 -     }
 -     if (localStorage?.getItem('is_refreshing') === '1') {
 -       timer.current = setTimeout(() => {
 -         getNewAccessToken()
 -       }, 1000)
 -       return null
 -     }
 -     const currentTokenExpireTime = getExpireTime(currentAccessToken)
 -     if (getCurrentTimeStamp() + advanceTime.current > currentTokenExpireTime) {
 -       localStorage?.setItem('is_refreshing', '1')
 -       const [e, res] = await fetchWithRetry(fetchNewToken({
 -         body: { refresh_token: currentRefreshToken },
 -       }) as Promise<CommonResponse & { data: { access_token: string; refresh_token: string } }>)
 -       if (e) {
 -         handleError()
 -         return e
 -       }
 -       const { access_token, refresh_token } = res.data
 -       localStorage?.setItem('is_refreshing', '0')
 -       localStorage?.setItem('console_token', access_token)
 -       localStorage?.setItem('refresh_token', refresh_token)
 -       const newTokenExpireTime = getExpireTime(access_token)
 -       timer.current = setTimeout(() => {
 -         getNewAccessToken()
 -       }, newTokenExpireTime - advanceTime.current - getCurrentTimeStamp())
 -     }
 -     else {
 -       const newTokenExpireTime = getExpireTime(currentAccessToken)
 -       timer.current = setTimeout(() => {
 -         getNewAccessToken()
 -       }, newTokenExpireTime - advanceTime.current - getCurrentTimeStamp())
 -     }
 -     return null
 -   }, [getExpireTime, getCurrentTimeStamp, handleError])
 - 
 -   useEffect(() => {
 -     return () => {
 -       clearTimeout(timer.current)
 -       localStorage?.removeItem('is_refreshing')
 -     }
 -   }, [])
 - 
 -   return {
 -     getNewAccessToken,
 -   }
 - }
 - 
 - export default useRefreshToken
 
 
  |