refactor(web): extract shared apiFetch helper, remove secret from webhook client type

This commit is contained in:
saravanakumardb1 2026-04-19 00:54:53 -07:00
parent fe2ab6010e
commit 38a15c0595
4 changed files with 32 additions and 70 deletions

View File

@ -2,29 +2,7 @@
* Agent Inbox API client talks to ChronoMind backend (port 4011).
*/
import { getBackendBaseURL } from './product-config';
function getToken(): string | null {
if (typeof window === 'undefined') return null;
return localStorage.getItem('chronomind_access_token');
}
async function apiFetch<T>(path: string, opts?: RequestInit): Promise<T> {
const token = getToken();
const res = await fetch(`${getBackendBaseURL()}${path}`, {
...opts,
headers: {
'Content-Type': 'application/json',
...(token ? { Authorization: `Bearer ${token}` } : {}),
...(opts?.headers ?? {}),
},
});
if (!res.ok) {
const body = await res.text().catch(() => '');
throw new Error(`${res.status}: ${body}`);
}
return res.json() as Promise<T>;
}
import { apiFetch } from './api-helpers';
// ── Types ──

View File

@ -0,0 +1,29 @@
/**
* Shared API helpers for ChronoMind web clients.
*
* Provides a common fetch wrapper with auth token injection.
*/
import { getBackendBaseURL } from './product-config';
export function getAccessToken(): string | null {
if (typeof window === 'undefined') return null;
return localStorage.getItem('chronomind_access_token');
}
export async function apiFetch<T>(path: string, opts?: RequestInit): Promise<T> {
const token = getAccessToken();
const res = await fetch(`${getBackendBaseURL()}${path}`, {
...opts,
headers: {
'Content-Type': 'application/json',
...(token ? { Authorization: `Bearer ${token}` } : {}),
...(opts?.headers ?? {}),
},
});
if (!res.ok) {
const body = await res.text().catch(() => '');
throw new Error(`${res.status}: ${body}`);
}
return res.json() as Promise<T>;
}

View File

@ -2,29 +2,7 @@
* Day Planner API client talks to ChronoMind backend (port 4011).
*/
import { getBackendBaseURL } from './product-config';
function getToken(): string | null {
if (typeof window === 'undefined') return null;
return localStorage.getItem('chronomind_access_token');
}
async function apiFetch<T>(path: string, opts?: RequestInit): Promise<T> {
const token = getToken();
const res = await fetch(`${getBackendBaseURL()}${path}`, {
...opts,
headers: {
'Content-Type': 'application/json',
...(token ? { Authorization: `Bearer ${token}` } : {}),
...(opts?.headers ?? {}),
},
});
if (!res.ok) {
const body = await res.text().catch(() => '');
throw new Error(`${res.status}: ${body}`);
}
return res.json() as Promise<T>;
}
import { apiFetch } from './api-helpers';
// ── Types ──

View File

@ -2,29 +2,7 @@
* Webhook management API client talks to ChronoMind backend.
*/
import { getBackendBaseURL } from './product-config';
function getToken(): string | null {
if (typeof window === 'undefined') return null;
return localStorage.getItem('chronomind_access_token');
}
async function apiFetch<T>(path: string, opts?: RequestInit): Promise<T> {
const token = getToken();
const res = await fetch(`${getBackendBaseURL()}${path}`, {
...opts,
headers: {
'Content-Type': 'application/json',
...(token ? { Authorization: `Bearer ${token}` } : {}),
...(opts?.headers ?? {}),
},
});
if (!res.ok) {
const body = await res.text().catch(() => '');
throw new Error(`${res.status}: ${body}`);
}
return res.json() as Promise<T>;
}
import { apiFetch } from './api-helpers';
// ── Types ──
@ -33,7 +11,6 @@ export interface WebhookSubscription {
url: string;
events: string[];
active: boolean;
secret: string;
description?: string;
createdAt: string;
consecutiveFailures: number;