Files
YTChatHub/client/lib/api.ts
T
yusufipek 6bcbd5400b Rewrite dashboard and overlay, single /events stream, static client served by the backend
Backend: one SSE stream for messages, selection, poll and connection status; reconnect with backoff; no on-disk Innertube session cache; mock only with MOCK_CHAT=1; binds to 127.0.0.1; serves client/out so production runs on one port. Full URLs for links YouTube truncates in chat.

Client: components split out, Lucide icons, stream title and status, on-air strip, search, pause, keyboard shortcuts, overlay settings dialog. Overlay themes, position, size, animation and auto-hide via URL, sized for 1080p and scaled with the source. New blueprint theme for the brand background.

Removed Tailwind, better-sqlite3, zod, the timezone helpers, Cline memory bank and AGENTS.md. Added ESLint, node:test tests and CI.
2026-09-02 22:05:58 +03:00

30 lines
965 B
TypeScript

import { BACKEND_URL } from './config';
async function call<T = unknown>(path: string, init?: RequestInit): Promise<T> {
const response = await fetch(`${BACKEND_URL}${path}`, init);
if (!response.ok) {
let message = `HTTP ${response.status}`;
try {
const body = await response.json();
if (body?.error) message = String(body.error);
} catch {
// body was not JSON
}
throw new Error(message);
}
return response.json() as Promise<T>;
}
const json = (body: unknown): RequestInit => ({
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(body)
});
export const api = {
connect: (liveId: string) => call<{ ok: true; liveId: string }>('/chat/connect', json({ liveId })),
disconnect: () => call('/chat/disconnect', { method: 'POST' }),
select: (id: string) => call('/overlay/selection', json({ id })),
clearSelection: () => call('/overlay/selection', { method: 'DELETE' })
};