import { z } from 'zod'; import { ActivityResponseSchema, ChatSyncStatusSchema, ChatSyncTriggerResponseSchema, FetchAllChatsResponseSchema, } from '../../../../../packages/api-contracts/src/index.js'; import { createDashboardRequest } from '../../api/request.js'; export const RawLogEntrySchema = z.strictObject({ timestamp: z.number(), level: z.union([z.literal('debug'), z.literal('info'), z.literal('warn'), z.literal('error')]), message: z.string(), data: z.unknown().optional(), }); export const RawLogsResponseSchema = z.array(RawLogEntrySchema); export type RawLogEntry = z.infer; async function parseResponse( response: Response, schema: { parse(value: unknown): T }, ): Promise { const payload: unknown = await response.json(); if (!response.ok) { const message = typeof payload === 'object' && payload !== null && 'error' in payload && typeof payload.error === 'string' ? payload.error : `Request failed (${response.status})`; throw new Error(message); } return schema.parse(payload); } export function createOperationsApi(fetchImplementation?: typeof fetch) { const request = createDashboardRequest(fetchImplementation); return { async getActivity() { return parseResponse(await request('/api/activity'), ActivityResponseSchema); }, async getLogs(limit = 200) { return parseResponse( await request(`/api/logs?limit=${limit}`), RawLogsResponseSchema, ); }, async getSyncStatus() { return parseResponse(await request('/api/chats/sync'), ChatSyncStatusSchema); }, async triggerSync(kind: 'delta' | 'full') { const result = await parseResponse( await request(`/api/chats/sync/${kind}`, { method: 'POST' }), ChatSyncTriggerResponseSchema, ); if (!('success' in result)) throw new Error(result.error); if (!result.success) throw new Error(result.reason); return result; }, async fetchAllChats() { return parseResponse(await request('/api/chats/fetch-all', { method: 'POST' }), FetchAllChatsResponseSchema); }, }; } export const operationsApi = createOperationsApi();