Sync from /srv/compose/unified-media-manager
This commit is contained in:
64
frontend/src/api/client.ts
Normal file
64
frontend/src/api/client.ts
Normal file
@@ -0,0 +1,64 @@
|
||||
const API = import.meta.env.VITE_API_URL || ''
|
||||
|
||||
function getAPIKey(): string | null {
|
||||
return localStorage.getItem('umm_api_key')
|
||||
}
|
||||
|
||||
function authHeaders(): Record<string, string> {
|
||||
const key = getAPIKey()
|
||||
if (key) return { 'X-API-Key': key }
|
||||
return {}
|
||||
}
|
||||
|
||||
function jsonHeaders(): Record<string, string> {
|
||||
return { 'Content-Type': 'application/json', ...authHeaders() }
|
||||
}
|
||||
|
||||
export function setAPIKey(key: string) {
|
||||
localStorage.setItem('umm_api_key', key)
|
||||
}
|
||||
|
||||
export function clearAPIKey() {
|
||||
localStorage.removeItem('umm_api_key')
|
||||
}
|
||||
|
||||
export function hasAPIKey(): boolean {
|
||||
return !!getAPIKey()
|
||||
}
|
||||
|
||||
export async function fetchAPI<T>(path: string, init?: RequestInit): Promise<T> {
|
||||
const res = await fetch(`${API}${path}`, { ...init, headers: { ...authHeaders(), ...(init?.headers || {}) } })
|
||||
if (res.status === 401 && path.startsWith('/api/requests')) {
|
||||
throw new Error('Authentication required. Please set your API key in Settings.')
|
||||
}
|
||||
if (!res.ok) throw new Error(`API error: ${res.status}`)
|
||||
return res.json()
|
||||
}
|
||||
|
||||
export async function postAPI<T>(path: string, body: unknown, init?: RequestInit): Promise<T> {
|
||||
const res = await fetch(`${API}${path}`, {
|
||||
method: 'POST',
|
||||
headers: jsonHeaders(),
|
||||
body: JSON.stringify(body),
|
||||
...init,
|
||||
})
|
||||
if (!res.ok) throw new Error(`API error: ${res.status}`)
|
||||
return res.json()
|
||||
}
|
||||
|
||||
export async function putAPI<T>(path: string, body: unknown, init?: RequestInit): Promise<T> {
|
||||
const res = await fetch(`${API}${path}`, {
|
||||
method: 'PUT',
|
||||
headers: jsonHeaders(),
|
||||
body: JSON.stringify(body),
|
||||
...init,
|
||||
})
|
||||
if (!res.ok) throw new Error(`API error: ${res.status}`)
|
||||
return res.json()
|
||||
}
|
||||
|
||||
export async function deleteAPI<T>(path: string, init?: RequestInit): Promise<T> {
|
||||
const res = await fetch(`${API}${path}`, { method: 'DELETE', headers: authHeaders(), ...init })
|
||||
if (!res.ok) throw new Error(`API error: ${res.status}`)
|
||||
return res.json()
|
||||
}
|
||||
22
frontend/src/api/queryClient.tsx
Normal file
22
frontend/src/api/queryClient.tsx
Normal file
@@ -0,0 +1,22 @@
|
||||
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
|
||||
|
||||
const queryClient = new QueryClient({
|
||||
defaultOptions: {
|
||||
queries: {
|
||||
staleTime: 30 * 1000,
|
||||
gcTime: 5 * 60 * 1000,
|
||||
retry: 1,
|
||||
refetchOnWindowFocus: false,
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
export function QueryProvider({ children }: { children: React.ReactNode }) {
|
||||
return (
|
||||
<QueryClientProvider client={queryClient}>
|
||||
{children}
|
||||
</QueryClientProvider>
|
||||
)
|
||||
}
|
||||
|
||||
export { queryClient }
|
||||
Reference in New Issue
Block a user