| 12 | |
| 13 | // In-memory storage (replace with database for production) |
| 14 | class TokenStorage { |
| 15 | private sessions = new Map<string, UserSession>(); |
| 16 | |
| 17 | // Store a user session |
| 18 | storeSession(sessionId: string, session: UserSession): void { |
| 19 | this.sessions.set(sessionId, session); |
| 20 | } |
| 21 | |
| 22 | // Retrieve a user session |
| 23 | getSession(sessionId: string): UserSession | undefined { |
| 24 | return this.sessions.get(sessionId); |
| 25 | } |
| 26 | |
| 27 | // Remove a session |
| 28 | removeSession(sessionId: string): boolean { |
| 29 | return this.sessions.delete(sessionId); |
| 30 | } |
| 31 | |
| 32 | // Check if token needs refresh and refresh it |
| 33 | async refreshIfNeeded(sessionId: string): Promise<boolean> { |
| 34 | const session = this.sessions.get(sessionId); |
| 35 | if (!session || !session.expiresAt || !session.refreshToken) return false; |
| 36 | |
| 37 | // Check if token is expired or about to expire (within 5 minutes) |
| 38 | const now = new Date(); |
| 39 | const expiryDate = new Date(session.expiresAt); |
| 40 | const fiveMinutes = 5 * 60 * 1000; |
| 41 | |
| 42 | if (expiryDate.getTime() - now.getTime() > fiveMinutes) { |
| 43 | return false; // No need to refresh |
| 44 | } |
| 45 | |
| 46 | try { |
| 47 | // Refresh token using Octokit |
| 48 | const auth = await session.octokit.auth({ |
| 49 | type: "refresh", |
| 50 | refreshToken: session.refreshToken, |
| 51 | }) as Record<string, any>; |
| 52 | |
| 53 | // Update session with new tokens |
| 54 | session.accessToken = auth.token; |
| 55 | session.refreshToken = auth.refreshToken; |
| 56 | session.expiresAt = auth.expiresAt; |
| 57 | |
| 58 | // Update the stored session |
| 59 | this.sessions.set(sessionId, session); |
| 60 | return true; |
| 61 | } catch (error) { |
| 62 | console.error("Error refreshing token:", error); |
| 63 | return false; |
| 64 | } |
| 65 | } |
| 66 | } |
| 67 | |
| 68 | export const tokenStorage = new TokenStorage(); |
nothing calls this directly
no outgoing calls
no test coverage detected