Sync from /srv/compose/unified-media-manager

This commit is contained in:
Christopher Mayor
2026-04-24 10:45:19 -07:00
commit 7dbd00e537
132 changed files with 25394 additions and 0 deletions

View 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()
}

View 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 }