// Mythic Oracle — shared fetch wrapper, all API calls const BASE_URL = '/api'; async function request(path, options = {}) { const response = await fetch(`${BASE_URL}${path}`, { headers: { 'Content-Type': 'application/json' }, ...options, }); if (!response.ok) { let message = `Request failed: ${response.status}`; try { const body = await response.json(); if (body.error) message = body.error; } catch { // no JSON body on the error response } throw new Error(message); } if (response.status === 204) { return null; } return response.json(); } export function getCampaigns() { return request('/campaigns'); } export function createCampaign(data) { return request('/campaigns', { method: 'POST', body: JSON.stringify(data) }); } export function getCampaign(id) { return request(`/campaigns/${id}`); } export function updateCampaign(id, data) { return request(`/campaigns/${id}`, { method: 'PATCH', body: JSON.stringify(data) }); } export function deleteCampaign(id) { return request(`/campaigns/${id}`, { method: 'DELETE' }); } export function getSystems() { return request('/systems'); } export function getTable(name) { return request(`/tables/${name}`); } export async function getThreads(campaignId) { const { data } = await request(`/campaigns/${campaignId}/threads`); return data; } export async function createThread(campaignId, data) { const result = await request(`/campaigns/${campaignId}/threads`, { method: 'POST', body: JSON.stringify(data), }); return result.data; } export async function updateThread(campaignId, id, data) { const result = await request(`/campaigns/${campaignId}/threads/${id}`, { method: 'PUT', body: JSON.stringify(data), }); return result.data; } export async function deleteThread(campaignId, id) { const result = await request(`/campaigns/${campaignId}/threads/${id}`, { method: 'DELETE' }); return result.data; }