File size: 4,669 Bytes
3286713
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
b462c58
 
 
 
 
 
 
 
 
 
 
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
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
import type { EmilyResponse } from "@/lib/emily-api";
import type { DraftRecord, JournalRecord } from "@/lib/user-data";

export interface AuthUser {
  user_id: string;
  username: string;
}

interface AuthResponse {
  token: string;
  user_id: string;
  username: string;
}

const TOKEN_KEY = "echo-auth-token";

function getToken(): string {
  if (typeof window === "undefined") return "";
  return localStorage.getItem(TOKEN_KEY) ?? "";
}

function setToken(token: string): void {
  if (typeof window === "undefined") return;
  localStorage.setItem(TOKEN_KEY, token);
}

export function clearToken(): void {
  if (typeof window === "undefined") return;
  localStorage.removeItem(TOKEN_KEY);
}

export function hasToken(): boolean {
  return Boolean(getToken());
}

async function request<T>(path: string, init?: RequestInit): Promise<T> {
  const token = getToken();
  const response = await fetch(path, {
    ...init,
    headers: {
      "Content-Type": "application/json",
      ...(token ? { Authorization: `Bearer ${token}` } : {}),
      ...(init?.headers || {}),
    },
  });
  if (!response.ok) {
    const text = await response.text();
    throw new Error(text || `Request failed: ${response.status}`);
  }
  return response.json() as Promise<T>;
}

export async function register(username: string, password: string): Promise<AuthUser> {
  const data = await request<AuthResponse>("/api/backend/auth/register", {
    method: "POST",
    body: JSON.stringify({ username, password }),
  });
  setToken(data.token);
  return { user_id: data.user_id, username: data.username };
}

export async function login(username: string, password: string): Promise<AuthUser> {
  const data = await request<AuthResponse>("/api/backend/auth/login", {
    method: "POST",
    body: JSON.stringify({ username, password }),
  });
  setToken(data.token);
  return { user_id: data.user_id, username: data.username };
}

export async function me(): Promise<AuthUser> {
  return request<AuthUser>("/api/backend/auth/me");
}

export async function logout(): Promise<void> {
  try {
    await request<{ ok: boolean }>("/api/backend/auth/logout", { method: "POST" });
  } finally {
    clearToken();
  }
}

export async function analyzeJournal(payload: {
  request_id: string;
  user_id: string;
  user_input: string;
  trace_id: string;
  metadata?: Record<string, unknown>;
}): Promise<EmilyResponse> {
  return request<EmilyResponse>("/api/pipeline/analyze", {
    method: "POST",
    body: JSON.stringify(payload),
  });
}

export async function getEntries(): Promise<JournalRecord[]> {
  return request<JournalRecord[]>("/api/backend/data/entries");
}

export async function getDrafts(): Promise<DraftRecord[]> {
  return request<DraftRecord[]>("/api/backend/data/drafts");
}

export async function saveDraft(text: string, mood: string | null): Promise<DraftRecord> {
  return request<DraftRecord>("/api/backend/data/drafts", {
    method: "POST",
    body: JSON.stringify({ text, mood }),
  });
}

export async function deleteDraft(draftId: string): Promise<void> {
  await request<{ ok: boolean }>(`/api/backend/data/drafts/${draftId}`, { method: "DELETE" });
}

export async function getServerInsights(): Promise<string[]> {
  const data = await request<{ insights: string[] }>("/api/backend/data/insights");
  return data.insights;
}

export async function requestPasswordReset(username: string): Promise<string | null> {
  const data = await request<{ ok: boolean; reset_token?: string | null }>("/api/backend/auth/password-reset/request", {
    method: "POST",
    body: JSON.stringify({ username }),
  });
  return data.reset_token ?? null;
}

export async function confirmPasswordReset(token: string, newPassword: string): Promise<void> {
  await request<{ ok: boolean }>("/api/backend/auth/password-reset/confirm", {
    method: "POST",
    body: JSON.stringify({ token, new_password: newPassword }),
  });
}

export async function updateEntry(entryId: string, text: string, mood: string | null): Promise<JournalRecord> {
  return request<JournalRecord>(`/api/backend/data/entries/${entryId}`, {
    method: "PUT",
    body: JSON.stringify({ text, mood }),
  });
}

export async function deleteEntry(entryId: string): Promise<void> {
  await request<{ ok: boolean }>(`/api/backend/data/entries/${entryId}`, { method: "DELETE" });
}

export async function getProfile(): Promise<{ about: string }> {
  return request<{ about: string }>("/api/backend/profile");
}

export async function updateProfile(about: string): Promise<{ about: string }> {
  return request<{ about: string }>("/api/backend/profile", {
    method: "POST",
    body: JSON.stringify({ about }),
  });
}