Files
WRNexusJS/packages/csr/src/api-client.ts
T
Clintchiz 64ab20cc95
Quality / quality (ubuntu-latest) (push) Failing after 22s
Quality / quality (windows-latest) (push) Canceled after 0s
feat: add application productivity foundations
2026-08-23 11:13:03 +05:30

42 lines
1.7 KiB
TypeScript

export interface ApiRequest<Input = unknown> {
method?: string;
params?: Record<string, string | number>;
query?: Record<string, string | number | boolean | undefined>;
body?: Input;
}
export interface ApiClientOptions {
baseUrl?: string;
fetch?: (input: RequestInfo | URL, init?: RequestInit) => Promise<Response>;
}
/** Runtime used by generated API clients; throws a typed response error on non-2xx results. */
export function createApiClient(options: ApiClientOptions = {}) {
const fetcher = options.fetch ?? globalThis.fetch;
return async function call<Output, Input = unknown>(
template: string,
request: ApiRequest<Input> = {},
): Promise<Output> {
let path = template;
for (const [name, value] of Object.entries(request.params ?? {})) {
path = path.replace(`[${name}]`, encodeURIComponent(String(value)));
}
const url = new URL(path, options.baseUrl ?? globalThis.location?.origin ?? "http://localhost");
for (const [name, value] of Object.entries(request.query ?? {}))
if (value !== undefined) url.searchParams.set(name, String(value));
const response = await fetcher(url, {
method: request.method ?? (request.body === undefined ? "GET" : "POST"),
credentials: "same-origin",
headers: request.body === undefined ? undefined : { "content-type": "application/json" },
body: request.body === undefined ? undefined : JSON.stringify(request.body),
});
const data = response.status === 204 ? undefined : await response.json();
if (!response.ok)
throw Object.assign(
new Error((data as { error?: string })?.error ?? `HTTP ${response.status}`),
{ status: response.status, data },
);
return data as Output;
};
}