Skip to content

Commit 0665661

Browse files
committed
refactor: simplify GitHub authentication and token handling
1 parent 9c457c5 commit 0665661

2 files changed

Lines changed: 54 additions & 57 deletions

File tree

src/lib/initialization.ts

Lines changed: 28 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,41 +1,41 @@
11
import consola from "consola"
2-
import { FetchError } from "ofetch"
32

43
import { ensurePaths } from "~/lib/paths"
5-
import { tokenService } from "~/lib/token"
4+
import { readGithubToken, tokenService, writeGithubToken } from "~/lib/token"
5+
import { getDeviceCode } from "~/services/github/get-device-code"
66
import { getGitHubUser } from "~/services/github/get-user/service"
7+
import { pollAccessToken } from "~/services/github/poll-access-token"
78

89
import { getModels } from "../services/copilot/get-models/service"
9-
import { getGitHubToken } from "../services/github/get-token/service"
10+
import { state } from "./state"
1011

11-
async function initializeGithubAuthentication(): Promise<void> {
12-
const githubToken = await tokenService.getGithubToken()
12+
async function logUser() {
13+
const user = await getGitHubUser()
14+
consola.info(`Logged in as ${JSON.stringify(user.login)}\n`)
15+
}
1316

14-
try {
15-
if (githubToken) {
16-
// Set token in the service so github fetcher can use it
17-
await tokenService.setGithubToken(githubToken)
18-
await logUser()
19-
} else {
20-
throw new Error("No GitHub token available")
21-
}
22-
} catch (error) {
23-
if (error instanceof FetchError && error.statusCode !== 401) {
24-
consola.error("Authentication error:", {
25-
error,
26-
request: error.request,
27-
options: error.options,
28-
response: error.response,
29-
data: error.response?._data as Record<string, unknown>,
30-
})
31-
throw error
32-
}
17+
async function setupGitHubToken(): Promise<void> {
18+
const githubToken = await readGithubToken()
3319

34-
consola.info("Not logged in, getting new access token")
35-
const newToken = await initializeGithubToken()
36-
await tokenService.setGithubToken(newToken)
20+
if (githubToken) {
21+
state.githubToken = githubToken
3722
await logUser()
23+
24+
return
3825
}
26+
27+
consola.info("Not logged in, getting new access token")
28+
const response = await getDeviceCode()
29+
30+
consola.info(
31+
`Please enter the code "${response.user_code}" in ${response.verification_uri}`,
32+
)
33+
34+
const token = await pollAccessToken(response)
35+
await writeGithubToken(token)
36+
state.githubToken = token
37+
38+
await logUser()
3939
}
4040

4141
async function initializeCopilotToken(): Promise<void> {
@@ -49,19 +49,9 @@ async function logModelInformation(): Promise<void> {
4949
)
5050
}
5151

52-
async function initializeGithubToken() {
53-
consola.start("Getting GitHub device code")
54-
return await getGitHubToken()
55-
}
56-
57-
async function logUser() {
58-
const user = await getGitHubUser()
59-
consola.info(`Logged in as ${JSON.stringify(user.login)}\n`)
60-
}
61-
6252
export async function initializeApp() {
6353
await ensurePaths()
64-
await initializeGithubAuthentication()
54+
await setupGitHubToken()
6555
await initializeCopilotToken()
6656
await logModelInformation()
6757
}

src/lib/token.ts

Lines changed: 26 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,32 @@ import fs from "node:fs/promises"
44
import { PATHS } from "~/lib/paths"
55
import { getCopilotToken } from "~/services/copilot/get-token/copilot-token"
66

7+
import { state } from "./state"
8+
9+
export const readGithubToken = () =>
10+
fs.readFile(PATHS.GITHUB_TOKEN_PATH, "utf8")
11+
12+
export const writeGithubToken = (token: string) =>
13+
fs.writeFile(PATHS.GITHUB_TOKEN_PATH, token)
14+
15+
export const setupCopilotTokenRefresh = async () => {
16+
const { token, refresh_in } = await getCopilotToken()
17+
state.copilotToken = token
18+
19+
const refreshInterval = (refresh_in - 60) * 1000
20+
21+
setInterval(async () => {
22+
consola.start("Refreshing Copilot token")
23+
try {
24+
const { token } = await getCopilotToken()
25+
state.copilotToken = token
26+
} catch (error) {
27+
consola.error("Failed to refresh Copilot token:", error)
28+
throw error
29+
}
30+
}, refreshInterval)
31+
}
32+
733
// Simple token manager with basic encapsulation
834
export const tokenService = {
935
// Private token storage
@@ -12,25 +38,6 @@ export const tokenService = {
1238
copilot: undefined as string | undefined,
1339
},
1440

15-
// Get GitHub token
16-
async getGithubToken(): Promise<string | undefined> {
17-
if (!this._tokens.github) {
18-
try {
19-
this._tokens.github = await fs.readFile(PATHS.GITHUB_TOKEN_PATH, "utf8")
20-
} catch (error) {
21-
consola.warn("Failed to load GitHub token", error)
22-
}
23-
}
24-
25-
return this._tokens.github
26-
},
27-
28-
// Set GitHub token
29-
async setGithubToken(token: string): Promise<void> {
30-
this._tokens.github = token
31-
await fs.writeFile(PATHS.GITHUB_TOKEN_PATH, token)
32-
},
33-
3441
// Get Copilot token
3542
getCopilotToken(): string | undefined {
3643
return this._tokens.copilot

0 commit comments

Comments
 (0)