MCPcopy Create free account
hub / github.com/Tong89/smartNode / ApiClient

Class ApiClient

frontend/src/api/client.ts:65–187  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

63 * and share across the application.
64 */
65export class ApiClient {
66 private _baseUrl: string;
67 private _defaultTimeoutMs: number;
68
69 constructor(baseUrl?: string, defaultTimeoutMs = DEFAULT_TIMEOUT_MS) {
70 this._baseUrl = baseUrl !== undefined ? baseUrl : resolveApiBase();
71 this._defaultTimeoutMs = defaultTimeoutMs;
72 }
73
74 /** Current base URL (without trailing slash). */
75 get baseUrl(): string {
76 return this._baseUrl;
77 }
78
79 /** Update the base URL and persist it to localStorage if non-empty. */
80 setBaseUrl(value: string): void {
81 const normalized = (value || '').trim().replace(/\/$/, '');
82 this._baseUrl = normalized === window.location.origin ? '' : normalized;
83 if (this._baseUrl) {
84 localStorage.setItem('space_api_base', this._baseUrl);
85 } else {
86 localStorage.removeItem('space_api_base');
87 }
88 }
89
90 /** Build a fully-qualified URL for the given API path. */
91 url(path: string): string {
92 return `${this._baseUrl}${path}`;
93 }
94
95 /**
96 * Execute an HTTP request and return the parsed JSON response.
97 *
98 * - Injects `Authorization: Bearer <token>` when `smartnode_token` is set
99 * in localStorage and no `Authorization` header was provided.
100 * - Unwraps backend envelope `{ code: 0, data: T }` transparently.
101 * - Throws `ApiError` on non-2xx responses or timeout.
102 */
103 async request<T>(path: string, options: RequestOptions = {}): Promise<T> {
104 const { timeoutMs = this._defaultTimeoutMs, ...fetchOptions } = options;
105
106 const headers: Record<string, string> = {
107 'Content-Type': 'application/json',
108 ...((fetchOptions.headers as Record<string, string>) || {}),
109 };
110
111 const token = localStorage.getItem('smartnode_token');
112 if (token && !headers['Authorization']) {
113 headers['Authorization'] = `Bearer ${token}`;
114 }
115
116 let abortController: AbortController | undefined;
117 let timeoutId: ReturnType<typeof setTimeout> | undefined;
118
119 if (timeoutMs > 0) {
120 abortController = new AbortController();
121 timeoutId = setTimeout(() => abortController!.abort(), timeoutMs);
122 }

Callers

nothing calls this directly

Calls

no outgoing calls

Tested by

no test coverage detected