fix(repoList): handle Bad credentials error from GitHub API
Catch 401 responses in useRepos loadMore and expose hasCredentialError, then show a sign-in prompt in RepoList instead of an unhandled rejection.
This commit is contained in:
@@ -9,6 +9,7 @@ const STALE_TIME_MS = 20 * 60 * 1000
|
|||||||
|
|
||||||
const repos = ref<RepoBase[]>([])
|
const repos = ref<RepoBase[]>([])
|
||||||
const isReady = ref(false)
|
const isReady = ref(false)
|
||||||
|
const hasCredentialError = ref(false)
|
||||||
const currentPage = ref(0)
|
const currentPage = ref(0)
|
||||||
const totalCount = ref(0)
|
const totalCount = ref(0)
|
||||||
let lastFetchedAt = 0
|
let lastFetchedAt = 0
|
||||||
@@ -21,24 +22,38 @@ export const useRepos = () => {
|
|||||||
isReady.value = true
|
isReady.value = true
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
const octokit = await getOctokit()
|
try {
|
||||||
const nextPage = currentPage.value + 1
|
const octokit = await getOctokit()
|
||||||
const repoList = await octokit.request("GET /search/repositories", {
|
const nextPage = currentPage.value + 1
|
||||||
q: `user:${username.value}`,
|
const repoList = await octokit.request("GET /search/repositories", {
|
||||||
per_page: PER_PAGE,
|
q: `user:${username.value}`,
|
||||||
page: nextPage
|
per_page: PER_PAGE,
|
||||||
})
|
page: nextPage
|
||||||
currentPage.value = nextPage
|
})
|
||||||
totalCount.value = repoList.data.total_count
|
currentPage.value = nextPage
|
||||||
const newItems = repoList.data.items.map((item) => ({
|
totalCount.value = repoList.data.total_count
|
||||||
id: `${item.id}`,
|
const newItems = repoList.data.items.map((item) => ({
|
||||||
name: item.name,
|
id: `${item.id}`,
|
||||||
isPrivate: item.private
|
name: item.name,
|
||||||
}))
|
isPrivate: item.private
|
||||||
repos.value = [...repos.value, ...newItems].sort((a, b) =>
|
}))
|
||||||
a.name < b.name ? -1 : 1
|
repos.value = [...repos.value, ...newItems].sort((a, b) =>
|
||||||
)
|
a.name < b.name ? -1 : 1
|
||||||
isReady.value = true
|
)
|
||||||
|
} catch (err: unknown) {
|
||||||
|
if (
|
||||||
|
typeof err === "object" &&
|
||||||
|
err !== null &&
|
||||||
|
"status" in err &&
|
||||||
|
(err as { status: number }).status === 401
|
||||||
|
) {
|
||||||
|
hasCredentialError.value = true
|
||||||
|
} else {
|
||||||
|
throw err
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
isReady.value = true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const canLoadMore = computed(() => repos.value.length < totalCount.value)
|
const canLoadMore = computed(() => repos.value.length < totalCount.value)
|
||||||
@@ -50,10 +65,11 @@ export const useRepos = () => {
|
|||||||
currentPage.value = 0
|
currentPage.value = 0
|
||||||
totalCount.value = 0
|
totalCount.value = 0
|
||||||
isReady.value = false
|
isReady.value = false
|
||||||
|
hasCredentialError.value = false
|
||||||
}
|
}
|
||||||
lastFetchedAt = Date.now()
|
lastFetchedAt = Date.now()
|
||||||
loadMore()
|
loadMore()
|
||||||
}
|
}
|
||||||
|
|
||||||
return { repos, isReady, canLoadMore, loadMore }
|
return { repos, isReady, hasCredentialError, canLoadMore, loadMore }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,12 +2,13 @@
|
|||||||
import { vInfiniteScroll } from "@vueuse/components"
|
import { vInfiniteScroll } from "@vueuse/components"
|
||||||
|
|
||||||
import GoBack from "@/components/GoBack.vue"
|
import GoBack from "@/components/GoBack.vue"
|
||||||
|
import SignInGithub from "@/components/SignInGithub.vue"
|
||||||
import { useGitHubLogin } from "@/hooks/useGitHubLogin.hook"
|
import { useGitHubLogin } from "@/hooks/useGitHubLogin.hook"
|
||||||
import { useRepos } from "@/hooks/useRepos.hook"
|
import { useRepos } from "@/hooks/useRepos.hook"
|
||||||
import { useRepoList } from "@/modules/repo/hooks/useRepoList.hook"
|
import { useRepoList } from "@/modules/repo/hooks/useRepoList.hook"
|
||||||
|
|
||||||
const { username } = useGitHubLogin()
|
const { username } = useGitHubLogin()
|
||||||
const { isReady } = useRepos()
|
const { isReady, hasCredentialError } = useRepos()
|
||||||
const {
|
const {
|
||||||
favoriteRepos,
|
favoriteRepos,
|
||||||
otherRepos,
|
otherRepos,
|
||||||
@@ -26,6 +27,10 @@ const {
|
|||||||
<h1 class="title is-1">Repositories</h1>
|
<h1 class="title is-1">Repositories</h1>
|
||||||
<go-back />
|
<go-back />
|
||||||
<div v-if="!isReady">loading...</div>
|
<div v-if="!isReady">loading...</div>
|
||||||
|
<div v-else-if="hasCredentialError">
|
||||||
|
<p>Your GitHub credentials are invalid or expired.</p>
|
||||||
|
<sign-in-github />
|
||||||
|
</div>
|
||||||
<div v-else class="columns is-centered">
|
<div v-else class="columns is-centered">
|
||||||
<div class="column is-one-third">
|
<div class="column is-one-third">
|
||||||
<table
|
<table
|
||||||
|
|||||||
Reference in New Issue
Block a user