Files
dip-ids/frontend/composables/useApi.ts
T
kilyabin 78e5c90ed0 feat: healthcheck backend and fix data types
also small various features
2026-04-28 00:10:06 +04:00

81 lines
2.3 KiB
TypeScript

const RETRY_DELAYS = [0, 500, 1500]
const CACHE_TTL_MS = 24 * 60 * 60 * 1000
function cacheKey(url: string) {
return `nids_cache:${url}`
}
function saveToCache(url: string, data: unknown) {
try {
localStorage.setItem(cacheKey(url), JSON.stringify({ data, ts: Date.now() }))
} catch {}
}
function loadFromCache<T>(url: string): T | null {
try {
const raw = localStorage.getItem(cacheKey(url))
if (!raw) return null
const { data, ts } = JSON.parse(raw)
if (Date.now() - ts > CACHE_TTL_MS) return null
return data as T
} catch {
return null
}
}
// Базовый fetch к Go API
export function useApi() {
async function get<T>(path: string, params?: Record<string, string | number>): Promise<T> {
const url = new URL('/api' + path, window.location.origin)
if (params) {
Object.entries(params).forEach(([k, v]) => url.searchParams.set(k, String(v)))
}
const urlStr = url.toString()
let lastErr: unknown
for (let i = 0; i < RETRY_DELAYS.length; i++) {
if (i > 0) await new Promise(r => setTimeout(r, RETRY_DELAYS[i]))
try {
const res = await fetch(urlStr, { signal: AbortSignal.timeout(5000) })
if (!res.ok) throw new Error(await res.text())
const data = await res.json() as T
saveToCache(urlStr, data)
return data
} catch (e) {
lastErr = e
}
}
const cached = loadFromCache<T>(urlStr)
if (cached !== null) return cached
throw lastErr
}
async function post<T>(path: string, body?: unknown) {
const res = await fetch('/api' + path, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: body ? JSON.stringify(body) : undefined,
})
if (!res.ok) throw new Error(await res.text())
return res.json() as Promise<T>
}
async function del(path: string) {
const res = await fetch('/api' + path, { method: 'DELETE' })
if (!res.ok) throw new Error(await res.text())
return res.json()
}
async function upload(path: string, file: File) {
const form = new FormData()
form.append('file', file)
const res = await fetch('/api' + path, { method: 'POST', body: form })
if (!res.ok) throw new Error(await res.text())
return res.json()
}
return { get, post, del, upload }
}