soulsync/webui/src/app/api-client.ts
Antti Kettunen fec66e4de8
feat(webui): expose shell status in root context
- add a shared shell client and root /status query
- attach shell status to the TanStack root context for React routes
- keep the shell bridge types and test setup aligned with the new status data
2026-05-23 21:23:32 +03:00

50 lines
1.3 KiB
TypeScript

import type { ResponsePromise } from 'ky';
import ky, { HTTPError } from 'ky';
const apiBaseUrl =
typeof globalThis.location === 'object'
? new URL('/api/', globalThis.location.origin).toString()
: 'http://localhost/api/';
const shellBaseUrl =
typeof globalThis.location === 'object'
? new URL('/', globalThis.location.origin).toString()
: 'http://localhost/';
export const apiClient = ky.create({
baseUrl: apiBaseUrl,
retry: 0,
});
export const shellClient = ky.create({
baseUrl: shellBaseUrl,
retry: 0,
});
export async function readJson<T>(promise: ResponsePromise<T>): Promise<T> {
try {
return await promise.json<T>();
} catch (error) {
if (error instanceof HTTPError) {
error.message = getHttpErrorMessage(error.data, error.message);
}
throw error;
}
}
type JsonErrorPayload = {
error?: unknown;
message?: unknown;
};
function getHttpErrorMessage(data: unknown, fallback: string): string {
if (typeof data === 'string' && data.trim()) return data;
if (!data || typeof data !== 'object') return fallback;
const payload = data as JsonErrorPayload;
if (typeof payload.error === 'string' && payload.error.trim()) return payload.error;
if (typeof payload.message === 'string' && payload.message.trim()) return payload.message;
return fallback;
}