refactor(github-content): expose conflict info and add latest-sha lookup

updateFile/createFile now return { sha, conflict } so 409/422 from GitHub
can drive a UI flow instead of being swallowed as a generic save error.
Also adds fetchLatestSha(path) for cheap freshness checks against HEAD.
This commit is contained in:
Julien Calixte
2026-05-03 23:32:37 +02:00
parent dffee40776
commit d8a59467a0
3 changed files with 34 additions and 8 deletions

View File

@@ -74,7 +74,7 @@ export const useCheckboxCommit = ({
isCommitting.value = true
const newSha = await updateFile({
const { sha: newSha } = await updateFile({
content: pendingContent.value,
path: pathValue,
sha: currentSha.value

View File

@@ -2,6 +2,8 @@ import { getOctokit } from "@/modules/repo/services/octo"
import { encodeUTF8ToBase64 } from "@/utils/decodeBase64ToUTF8"
import { confirmMessage, errorMessage } from "@/utils/notif"
const isConflictStatus = (status: number) => status === 409 || status === 422
export const useGitHubContent = ({
user,
repo
@@ -9,6 +11,21 @@ export const useGitHubContent = ({
user: string
repo: string
}) => {
const fetchLatestSha = async (path: string): Promise<string | null> => {
try {
const octokit = await getOctokit()
const response = await octokit.request(
"GET /repos/{owner}/{repo}/contents/{path}",
{ owner: user, repo, path }
)
const data = response?.data
if (Array.isArray(data) || !data) return null
return "sha" in data ? data.sha : null
} catch {
return null
}
}
const putFile = async ({
content,
path,
@@ -17,7 +34,7 @@ export const useGitHubContent = ({
content: string
path: string
sha?: string
}) => {
}): Promise<{ sha: string | null; conflict: boolean }> => {
try {
const octokit = await getOctokit()
@@ -35,18 +52,27 @@ export const useGitHubContent = ({
confirmMessage("✅ Note saved")
return response?.data.content?.sha ?? null
return { sha: response?.data.content?.sha ?? null, conflict: false }
} catch (error) {
const status = (error as { status?: number })?.status
if (status && isConflictStatus(status)) {
errorMessage("⚠ Conflict: this note changed on GitHub")
console.warn(error)
return { sha: null, conflict: true }
}
errorMessage("❌ Note could not be saved")
console.warn(error)
return { sha: null, conflict: false }
}
return null
}
return {
updateFile: async (props: { content: string; path: string; sha: string }) =>
putFile(props),
fetchLatestSha,
updateFile: async (props: {
content: string
path: string
sha: string
}) => putFile(props),
createFile: async (props: { content: string; path: string }) =>
putFile(props)
}

View File

@@ -82,7 +82,7 @@ watch(mode, async (newMode) => {
newContent.value
}`
const newSha = await createFile({
const { sha: newSha } = await createFile({
content,
path: newContentPath
})