Files
scoreodonto.com/frontend/views/newwhats/services/nwClient.ts
T
VPS 4 Builder 3042ddca38 feat(newwhats): frontend do plugin (Inbox/Sessions/Secretária) em tela cheia
- /wa-inbox, /wa-sessions e /wa-secretaria rodam sem a sidebar do scoreodonto
  (isStandaloneView); cada tela tem seu "Voltar" (Secretária ganhou botão na ThinNav).
- SessionsView: banner "Você já possui acesso ao WhatsApp" quando há sessão ativa.
- avatares: usa a URL do CDN (contactAvatarUrl/instance.avatar) direto; Avatar
  exibe sem depender de version; self-heal no onError re-busca a foto atual.
- deps: framer-motion, immer. Dev override com HMR (docker-compose.dev.yml).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-01 20:54:24 +02:00

44 lines
1.8 KiB
TypeScript

// Cliente base do satélite NewWhats → /api/nw/v1/* (proxy do backend → motor
// /api/ext/v1/*). Auth: Bearer do scoreodonto (localStorage SCOREODONTO_AUTH_TOKEN).
// Retorna JSON já parseado; em erro, lança Error com `.response = { status, data }`
// (mesmo shape do axios, que o código portado do motor espera).
const API: string = (import.meta as any).env?.VITE_API_URL || '/api';
const TOKEN_KEY = 'SCOREODONTO_AUTH_TOKEN';
export function nwToken(): string | null {
try { return localStorage.getItem(TOKEN_KEY); } catch { return null; }
}
function authHeaders(extra?: Record<string, string>): Record<string, string> {
const t = nwToken();
return { ...(t ? { Authorization: `Bearer ${t}` } : {}), ...(extra || {}) };
}
async function req(method: string, path: string, body?: any): Promise<any> {
const isForm = typeof FormData !== 'undefined' && body instanceof FormData;
const res = await fetch(`${API}/nw/v1${path}`, {
method,
headers: authHeaders(isForm ? undefined : (body != null ? { 'Content-Type': 'application/json' } : undefined)),
body: body == null ? undefined : (isForm ? body : JSON.stringify(body)),
});
const text = await res.text();
let data: any = null;
try { data = text ? JSON.parse(text) : null; } catch { data = text; }
if (!res.ok) {
const err: any = new Error((data && data.error) || `${res.status}`);
err.response = { status: res.status, data };
throw err;
}
return data;
}
export const nw = {
get: (p: string) => req('GET', p),
post: (p: string, body?: any) => req('POST', p, body),
put: (p: string, body?: any) => req('PUT', p, body),
patch: (p: string, body?: any) => req('PATCH', p, body),
delete: (p: string) => req('DELETE', p),
// URL base ('/api' relativo ou absoluta) — usada pelo socketService p/ o WS.
base: () => API,
};