database integration
Deploy photobooth / deploy (push) Has been cancelled

This commit is contained in:
2026-05-26 09:07:16 +07:00
parent a90b3a85a2
commit 100e5c3a87
18 changed files with 1068 additions and 108 deletions
+92
View File
@@ -0,0 +1,92 @@
const API_BASE_URL = String(import.meta.env.VITE_API_BASE_URL || '').replace(/\/$/, '')
let accessToken = ''
let refreshHandler = null
export function setAccessToken(token) {
accessToken = token || ''
}
export function clearAccessToken() {
accessToken = ''
}
export function setRefreshHandler(handler) {
refreshHandler = handler
}
function buildUrl(path) {
if (!API_BASE_URL) return path
if (/^https?:\/\//i.test(path)) return path
return `${API_BASE_URL}${path.startsWith('/') ? '' : '/'}${path}`
}
async function readBody(res) {
if (res.status === 204) return null
const contentType = res.headers.get('content-type') || ''
if (contentType.includes('application/json')) return res.json()
return res.text()
}
function normalizeError(data) {
if (!data) return new Error('Request failed')
if (typeof data === 'string') return new Error(data)
if (typeof data?.message === 'string') return new Error(data.message)
return new Error('Request failed')
}
async function tryRefresh() {
if (!refreshHandler) return false
try {
const token = await refreshHandler()
if (!token) {
clearAccessToken()
return false
}
setAccessToken(token)
return true
} catch {
clearAccessToken()
return false
}
}
export async function apiRequest(
path,
{ method = 'GET', body, headers = {}, skipAuth = false, skipRefresh = false } = {},
) {
const url = buildUrl(path)
const finalHeaders = new Headers(headers)
if (!skipAuth && accessToken) {
finalHeaders.set('Authorization', `Bearer ${accessToken}`)
}
let finalBody = body
if (body && !(body instanceof FormData) && typeof body === 'object') {
finalHeaders.set('Content-Type', 'application/json')
finalBody = JSON.stringify(body)
}
const res = await fetch(url, {
method,
headers: finalHeaders,
body: finalBody,
credentials: 'include',
})
if (res.status === 401 && !skipRefresh) {
const refreshed = await tryRefresh()
if (refreshed) {
return apiRequest(path, { method, body, headers, skipAuth, skipRefresh: true })
}
}
const data = await readBody(res)
if (!res.ok) {
throw normalizeError(data)
}
return data
}