()
| 110 | * expire and skip the refresh path entirely. |
| 111 | */ |
| 112 | export async function getValidAccessToken(): Promise<string | null> { |
| 113 | const tokens = loadTokens(); |
| 114 | if (!tokens) return null; |
| 115 | |
| 116 | if (!isTokenExpired(tokens)) { |
| 117 | return tokens.access_token; |
| 118 | } |
| 119 | |
| 120 | if (!tokens.refresh_token) { |
| 121 | return null; |
| 122 | } |
| 123 | |
| 124 | try { |
| 125 | const newTokens = await refreshAccessToken(tokens.refresh_token); |
| 126 | saveTokens(newTokens); |
| 127 | return newTokens.access_token; |
| 128 | } catch { |
| 129 | return null; |
| 130 | } |
| 131 | } |
| 132 | |
| 133 | interface TokenErrorResponse { |
| 134 | error?: string; |
no test coverage detected