File size: 2,934 Bytes
b03f016
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
import type { Experiment, ExperimentDetail, SubExperiment, ExperimentNote, ActivityLogEntry, Artifact } from "./types";

const BASE = "/api/experiments";

async function fetchJSON<T>(url: string, opts?: RequestInit): Promise<T> {
  const res = await fetch(url, {
    headers: { "Content-Type": "application/json" },
    ...opts,
  });
  if (!res.ok) {
    const err = await res.json().catch(() => ({ error: res.statusText }));
    throw new Error(err.error || res.statusText);
  }
  return res.json();
}

export const experimentsApi = {
  list() {
    return fetchJSON<Experiment[]>(`${BASE}/`);
  },

  get(id: string) {
    return fetchJSON<ExperimentDetail>(`${BASE}/${id}`);
  },

  create(data: Partial<Experiment>) {
    return fetchJSON<Experiment>(`${BASE}/`, {
      method: "POST",
      body: JSON.stringify(data),
    });
  },

  update(id: string, data: Partial<Experiment>) {
    return fetchJSON<Experiment>(`${BASE}/${id}`, {
      method: "PUT",
      body: JSON.stringify(data),
    });
  },

  delete(id: string) {
    return fetchJSON<{ status: string }>(`${BASE}/${id}`, { method: "DELETE" });
  },

  createSub(expId: string, data: Partial<SubExperiment>) {
    return fetchJSON<SubExperiment>(`${BASE}/${expId}/subs`, {
      method: "POST",
      body: JSON.stringify(data),
    });
  },

  updateSub(expId: string, subId: string, data: Partial<SubExperiment>) {
    return fetchJSON<SubExperiment>(`${BASE}/${expId}/subs/${subId}`, {
      method: "PUT",
      body: JSON.stringify(data),
    });
  },

  deleteSub(expId: string, subId: string) {
    return fetchJSON<{ status: string }>(`${BASE}/${expId}/subs/${subId}`, { method: "DELETE" });
  },

  // Notes
  createNote(expId: string, data: Partial<ExperimentNote>) {
    return fetchJSON<ExperimentNote>(`${BASE}/${expId}/notes`, {
      method: "POST",
      body: JSON.stringify(data),
    });
  },

  updateNote(expId: string, noteId: string, data: Partial<ExperimentNote>) {
    return fetchJSON<ExperimentNote>(`${BASE}/${expId}/notes/${noteId}`, {
      method: "PUT",
      body: JSON.stringify(data),
    });
  },

  deleteNote(expId: string, noteId: string) {
    return fetchJSON<{ status: string }>(`${BASE}/${expId}/notes/${noteId}`, { method: "DELETE" });
  },

  sync() {
    return fetchJSON<{ status: string }>(`${BASE}/sync`, { method: "POST" });
  },

  getSummary() {
    return fetchJSON<{ content_md: string; updated: string }>(`${BASE}/summary`);
  },

  getActivityLog(expId: string, filters?: { scope?: string; type?: string }) {
    const params = new URLSearchParams();
    if (filters?.scope) params.set("scope", filters.scope);
    if (filters?.type) params.set("type", filters.type);
    const qs = params.toString();
    return fetchJSON<ActivityLogEntry[]>(`${BASE}/${expId}/activity-log${qs ? `?${qs}` : ""}`);
  },

  getArtifacts(expId: string) {
    return fetchJSON<Artifact[]>(`${BASE}/${expId}/artifacts`);
  },
};