From 38a15c0595ae8bf8b67589f8642f20dd28b139d6 Mon Sep 17 00:00:00 2001 From: saravanakumardb1 Date: Sun, 19 Apr 2026 00:54:53 -0700 Subject: [PATCH] refactor(web): extract shared apiFetch helper, remove secret from webhook client type --- web/src/lib/agent-inbox-client.ts | 24 +----------------------- web/src/lib/api-helpers.ts | 29 +++++++++++++++++++++++++++++ web/src/lib/planner-client.ts | 24 +----------------------- web/src/lib/webhook-client.ts | 25 +------------------------ 4 files changed, 32 insertions(+), 70 deletions(-) create mode 100644 web/src/lib/api-helpers.ts diff --git a/web/src/lib/agent-inbox-client.ts b/web/src/lib/agent-inbox-client.ts index d64b1d9..d793aef 100644 --- a/web/src/lib/agent-inbox-client.ts +++ b/web/src/lib/agent-inbox-client.ts @@ -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(path: string, opts?: RequestInit): Promise { - 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; -} +import { apiFetch } from './api-helpers'; // ── Types ── diff --git a/web/src/lib/api-helpers.ts b/web/src/lib/api-helpers.ts new file mode 100644 index 0000000..23d57b9 --- /dev/null +++ b/web/src/lib/api-helpers.ts @@ -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(path: string, opts?: RequestInit): Promise { + 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; +} diff --git a/web/src/lib/planner-client.ts b/web/src/lib/planner-client.ts index 3255341..529d5b6 100644 --- a/web/src/lib/planner-client.ts +++ b/web/src/lib/planner-client.ts @@ -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(path: string, opts?: RequestInit): Promise { - 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; -} +import { apiFetch } from './api-helpers'; // ── Types ── diff --git a/web/src/lib/webhook-client.ts b/web/src/lib/webhook-client.ts index d1db92f..213059e 100644 --- a/web/src/lib/webhook-client.ts +++ b/web/src/lib/webhook-client.ts @@ -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(path: string, opts?: RequestInit): Promise { - 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; -} +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;